Spring MVC

Spring Boot 有许多包括 Spring MVC 的启动器。请注意,某些启动器包含对 Spring MVC 的依赖项,而不是直接包含它。本部分回答有关 Spring MVC 和 Spring Boot 的常见问题。

Write a JSON REST Service

只要类路径上存在 Jackson2,Spring Boot 应用程序中的任何 Spring @RestController 都应默认呈现 JSON 响应,如下例所示:

只要 MyThing 可以由 Jackson2 序列化(对于普通 POJO 或 Groovy 对象为 true),http://localhost:8080/thing 默认提供其 JSON 表示。请注意,在浏览器中,您有时可能会看到 XML 响应,因为浏览器往往会发送首选 XML 的接受标头。

Write an XML REST Service

如果您在类路径上拥有 Jackson XML 扩展(jackson-dataformat-xml),则可以使用它来呈现 XML 响应。我们用于 JSON 的先前示例将起作用。要使用 Jackson XML 呈现器,请将以下依赖项添加到您的项目:

<dependency>
	<groupId>com.fasterxml.jackson.dataformat</groupId>
	<artifactId>jackson-dataformat-xml</artifactId>
</dependency>

如果没有 Jackson 的 XML 扩展,并且有 JAXB,则可以通过添加对被注释为 @XmlRootElementMyThing 的额外要求,呈现 XML,如下例所示:

您需要确保 JAXB 库是您项目的一部分,例如通过添加:

<dependency>
	<groupId>org.glassfish.jaxb</groupId>
	<artifactId>jaxb-runtime</artifactId>
</dependency>

要让服务器呈现 XML 而不是 JSON,您可能需要发送 Accept: text/xml 标头(或使用浏览器)。

Customize the Jackson ObjectMapper

Spring MVC(客户端和服务器端)使用 HttpMessageConverters 在 HTTP 交换中协商内容转换。如果您在类路径上有 Jackson,那么您已经获得了由 Jackson2ObjectMapperBuilder 提供的默认转换器(实例已为您自动配置)。

ObjectMapper(或 Jackson XML 转换器的 XmlMapper)实例(默认创建)具有以下自定义属性:

  • MapperFeature.DEFAULT_VIEW_INCLUSION is disabled

  • DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES is disabled

  • SerializationFeature.WRITE_DATES_AS_TIMESTAMPS is disabled

  • SerializationFeature.WRITE_DURATIONS_AS_TIMESTAMPS is disabled

Spring Boot 还具有一些功能,可以更轻松地自定义此行为。

您可以使用环境配置 ObjectMapperXmlMapper 实例。Jackson 提供了一套丰富的开关功能,可用于配置其处理的各个方面。这些功能在多个枚举(在 Jackson 中)中进行了描述,该枚举映射到环境中的属性:

Enum Property Values

com.fasterxml.jackson.databind.cfg.EnumFeature

spring.jackson.datatype.enum.<feature_name>

true, false

com.fasterxml.jackson.databind.cfg.JsonNodeFeature

spring.jackson.datatype.json-node.<feature_name>

true, false

com.fasterxml.jackson.databind.DeserializationFeature

spring.jackson.deserialization.<feature_name>

true, false

com.fasterxml.jackson.core.JsonGenerator.Feature

spring.jackson.generator.<feature_name>

true, false

com.fasterxml.jackson.databind.MapperFeature

spring.jackson.mapper.<feature_name>

true, false

com.fasterxml.jackson.core.JsonParser.Feature

spring.jackson.parser.<feature_name>

true, false

com.fasterxml.jackson.databind.SerializationFeature

spring.jackson.serialization.<feature_name>

true, false

com.fasterxml.jackson.annotation.JsonInclude.Include

configprop:spring.jackson.default-property-inclusion[]

alwaysnon_nullnon_absentnon_defaultnon_empty

例如,若要启用 pretty print,请设置`spring.jackson.serialization.indent_output=true`。请注意,由于使用了relaxed bindingindent_output`的大小写不必匹配相应枚举常数的大小写,即`INDENT_OUTPUT

这种基于环境的配置应用于自动配置的`Jackson2ObjectMapperBuilder`Bean,并应用于使用builder创建的任何映射器,包括自动配置的`ObjectMapper`Bean。

上下文的`Jackson2ObjectMapperBuilder`可以通过一个或多个`Jackson2ObjectMapperBuilderCustomizer`Beans进行定制。此类定制器Beans可以排序(Boot自己的定制器有0的序数),从而允许在Boot定制之前和之后都应用额外的定制。

任何`com.fasterxml.jackson.databind.Module`类型的Bean都会自动注册到自动配置的`Jackson2ObjectMapperBuilder`中,并应用于它创建的任何`ObjectMapper`实例。当您向应用程序中添加新功能时,这种方式提供了一种全局机制,以贡献定制模块。

如果您想完全替换默认的`ObjectMapper`,请为该类型定义一个`@Bean`并将其标记为`@Primary`,或者,如果您更喜欢基于builder的方法,请定义一个`Jackson2ObjectMapperBuilder``@Bean`。请注意,在任何一种情况下,此操作都会禁用`ObjectMapper`的所有自动配置。

如果您提供任何`@Beans`,类型为`MappingJackson2HttpMessageConverter`,它们将替换MVC配置中的默认值。同样地,还提供了一个方便的`HttpMessageConverters`类型Bean(如果您使用默认MVC配置,该类型始终可用)。它有一些有用的方法来访问默认和用户增强消息转换器。

有关更多详情,请参阅"`Customize the @ResponseBody Rendering"部分和{code-spring-boot-autoconfigure-src}/web/servlet/WebMvcAutoConfiguration.java[`WebMvcAutoConfiguration]源代码。

Customize the @ResponseBody Rendering

Spring使用`HttpMessageConverters`来呈现`@ResponseBody`(或`@RestController`的响应)。您可在Spring Boot上下文中添加适当类型的Bean,以贡献其他转换器。如果您添加的Bean属于在任何情况下都将包含的类型(例如,`MappingJackson2HttpMessageConverter`用于JSON转换),它将替换默认值。还提供了一个方便的`HttpMessageConverters`类型Bean,如果您使用默认MVC配置,则它始终可用。它有一些有用的方法来访问默认和用户增强消息转换器(例如,如果您想将它们手动注入定制的`RestTemplate`时,它会很有用)。

与在正常MVC使用中一样,您提供的任何`WebMvcConfigurer`Bean也可以通过覆盖`configureMessageConverters`方法来贡献转换器。但是,与正常MVC不同,您只能提供您需要的额外转换器(因为Spring Boot使用相同的机制来贡献其默认值)。最后,如果您通过提供自己的`@EnableWebMvc`配置退出Spring Boot默认MVC配置,那么您可以通过使用`WebMvcConfigurationSupport`中的`getMessageConverters`完全控制并手动执行所有操作。

有关更多详情,请参阅{code-spring-boot-autoconfigure-src}/web/servlet/WebMvcAutoConfiguration.java[WebMvcAutoConfiguration]源代码。

Handling Multipart File Uploads

Spring Boot包含servlet 5 jakarta.servlet.http.Part`API,以支持文件上传。默认情况下,Spring Boot配置Spring MVC,为每个文件配置最大1MB的大小,在一个请求中的文件数据最大为10MB。您可以覆盖这些值、存储中间数据的位置(例如,到/tmp`目录)以及使用`MultipartProperties`类中公开的属性将数据刷新到磁盘的阈值。例如,如果您想指定文件不受限制,请将configprop:spring.servlet.multipart.max-file-size[]属性设置为`-1`。

当您想要接收多部分编码文件数据作为Spring MVC控制器处理程序方法中类型为`MultipartFile`的`@RequestParam`-注释的参数时,多部分支持非常有用。

有关更多详情,请参阅{code-spring-boot-autoconfigure-src}/web/servlet/MultipartAutoConfiguration.java[MultipartAutoConfiguration]源代码。

建议使用容器内置的多部分上传支持,而不是引入一个附加依赖项,如Apache Commons File Upload。

Switch Off the Spring MVC DispatcherServlet

默认情况下,所有内容都从您的应用程序根目录提供(/)。如果您希望映射到不同的路径,则可以按如下方式配置一个:

spring:
  mvc:
    servlet:
      path: "/mypath"

如果您有其他servlet,您可以为每个servlet声明类型为`Servlet`或`ServletRegistrationBean`的`@Bean`,Spring Boot将会将它们透明地注册到容器中。因为servlet就是以这种方式注册的,所以它们可以映射到`DispatcherServlet`的子上下文,而不调用它。

自己配置`DispatcherServlet`是不太常见的,但如果您确实需要这样做,则还必须提供类型为`DispatcherServletPath`的`@Bean`,以提供您的自定义`DispatcherServlet`的路径。

Switch off the Default MVC Configuration

完全控制MVC配置的最简单方法是提供您自己的`@EnableWebMvc`注释的`@Configuration`。这样做会将所有MVC配置都留给您处理。

Customize ViewResolvers

ViewResolver`是Spring MVC的核心组件,它将@Controller`中的视图名称转换为实际的`View`实现。请注意,ViewResolvers`主要用于UI应用程序,而不是REST风格的服务(`View`不用于呈现@ResponseBody`)。有多种`ViewResolver`实现可供选择,而且Spring自己不会明确提出意见,建议您使用哪一种。而Spring Boot会根据它在类路径和应用程序上下文中找到的内容,为您安装一个或两个`ViewResolver`。`DispatcherServlet`使用它在应用程序上下文中找到的所有解析器,依次尝试每个解析器,直到获得结果。如果您添加您自己的解析器,您必须注意解析器的顺序和添加的位置。

WebMvcAutoConfiguration 将以下 ViewResolvers 添加到您的上下文中:

  • 一个名为 '`defaultViewResolver` 的 InternalResourceViewResolver。此 InternalResourceViewResolver 找到可使用 DefaultServlet 渲染的物理资源(包括静态资源和 JSP 页面,如果您使用的话)。它将前缀和后缀应用于视图名称,然后在 servlet 上下文中使用该路径寻找物理资源(默认情况下两者都为空,但可以通过 spring.mvc.view.prefixspring.mvc.view.suffix 进行外部配置)。您可以通过提供同类型的一个 bean 来覆盖它。

  • 一个名为 '`beanNameViewResolver` 的 BeanNameViewResolver。这是视图解析器链中的一个有用成员,并选取与正在解析的 View 同名的任何 bean。没有必要覆盖或替换它。

  • 只有当实际上存在类型为 View 的 bean 时,才添加一个名为 '`viewResolver` 的 ContentNegotiatingViewResolver。这是一个复合解析器,委托给所有其他解析器,并尝试查找客户端发送的 '`Accept` HTTP 标头的匹配项。有一个有用的 blog about ContentNegotiatingViewResolver 可能您愿意研究它来了解更多信息,您还可以查看源代码来获取详细信息。您可以通过定义一个名为 '`viewResolver` 的 bean 来关闭自动配置 ContentNegotiatingViewResolver

  • 如果您使用 Thymeleaf,您还拥有一个名为 '`thymeleafViewResolver` 的 ThymeleafViewResolver。它通过使用前缀和后缀环绕视图名称来查找资源。前缀是 spring.thymeleaf.prefix,后缀是 spring.thymeleaf.suffix。前缀和后缀的默认值分别为 '`classpath:/templates/` 和 '`.html`。您可以通过提供同名的 bean 来覆盖 ThymeleafViewResolver

  • 如果您使用 FreeMarker,您还拥有一个名为 '`freeMarkerViewResolver` 的 FreeMarkerViewResolver。它通过使用前缀和后缀环绕视图名称,在加载器路径(已对外化为 spring.freemarker.templateLoaderPath 且具有默认值 '`classpath:/templates/)中查找资源。前缀对外化为 `spring.freemarker.prefix,后缀对外化为 spring.freemarker.suffix。前缀和后缀的默认值分别为空和 '`.ftlh`。您可以通过提供同名的 bean 来覆盖 FreeMarkerViewResolver

  • 如果您使用 Groovy 模板(实际上,如果 groovy-templates 在您的类路径中),您还拥有为名为 '`groovyMarkupViewResolver` 的 GroovyMarkupViewResolver。它通过使用前缀和后缀(对外化为 spring.groovy.template.prefixspring.groovy.template.suffix)环绕视图名称,在加载器路径中查找资源。前缀和后缀的默认值分别为 '`classpath:/templates/` 和 '`.tpl`。您可以通过提供同名的 bean 来覆盖 GroovyMarkupViewResolver

  • 如果您使用 Mustache,您还拥有一个名为 '`mustacheViewResolver` 的 MustacheViewResolver。它通过使用前缀和后缀环绕视图名称来查找资源。前缀是 spring.mustache.prefix,后缀是 spring.mustache.suffix。前缀和后缀的默认值分别为 '`classpath:/templates/` 和 '`.mustache`。您可以通过提供同名的 bean 来覆盖 MustacheViewResolver

有关更多详细信息,请参阅以下部分:

  • {code-spring-boot-autoconfigure-src}/web/servlet/WebMvcAutoConfiguration.java[WebMvcAutoConfiguration]

  • {code-spring-boot-autoconfigure-src}/thymeleaf/ThymeleafAutoConfiguration.java[ThymeleafAutoConfiguration]

  • {code-spring-boot-autoconfigure-src}/freemarker/FreeMarkerAutoConfiguration.java[FreeMarkerAutoConfiguration]

  • {code-spring-boot-autoconfigure-src}/groovy/template/GroovyTemplateAutoConfiguration.java[GroovyTemplateAutoConfiguration]