74. Spring MVC

74.1 编写 JSON REST 服务

默认情况下,只要 Jackson2 在 Classpath 上,Spring Boot 应用程序中的任何 Spring @RestController都应渲染 JSON 响应。例如:

@RestController
public class MyController {

    @RequestMapping("/thing")
    public MyThing thing() {
            return new MyThing();
    }

}

只要 Jackson_2 可以序列化MyThing(例如普通的 POJO 或 Groovy 对象),则localhost:8080/thing将默认为其提供 JSON 表示形式。有时在浏览器中您可能会看到 XML 响应,因为浏览器倾向于发送更喜欢 XML 的接受 Headers。

74.2 编写 XML REST 服务

如果您在 Classpath 上具有 Jackson XMLextensions(jackson-dataformat-xml),它将用于渲染 XML 响应,并且可以使用与 JSON 相同的示例。要使用它,请将以下依赖项添加到您的项目中:

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

您可能还想添加对 Woodstox 的依赖。它比 JDK 提供的默认 StAX 实现要快,并且还增加了漂亮的打印支持和改进的名称空间处理:

<dependency>
    <groupId>org.codehaus.woodstox</groupId>
    <artifactId>woodstox-core-asl</artifactId>
</dependency>

如果无法使用 Jackson 的 XMLextensions,则将使用 JAXB(JDK 中默认提供),并附加要求将MyThingComments 为@XmlRootElement

@XmlRootElement
public class MyThing {
    private String name;
    // .. getters and setters
}

要使服务器渲染 XML 而不是 JSON,您可能必须发送Accept: text/xmlHeaders(或使用浏览器)。

74.3 自定义 Jackson ObjectMapper

Spring MVC(Client 端和服务器端)使用HttpMessageConverters来协商 HTTP 交换中的内容转换。如果 Jackson 在 Classpath 中,则您已经获得Jackson2ObjectMapperBuilder提供的默认转换器,该转换器的实例已为您自动配置。

默认情况下创建的ObjectMapper(对于 Jackson XML 转换器,则为XmlMapper)实例具有以下自定义属性:

  • MapperFeature.DEFAULT_VIEW_INCLUSION已禁用

  • DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES已禁用

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

您可以使用环境配置ObjectMapperXmlMapper实例。Jackson 提供了一套广泛的简单的开/关功能,可用于配置其处理的各个方面。在 Jackson 的六个枚举中描述了这些功能,这些枚举 Map 到环境中的属性:

Jackson enumEnvironment property
com.fasterxml.jackson.databind.DeserializationFeaturespring.jackson.deserialization.<feature_name>=true|false
com.fasterxml.jackson.core.JsonGenerator.Featurespring.jackson.generator.<feature_name>=true|false
com.fasterxml.jackson.databind.MapperFeaturespring.jackson.mapper.<feature_name>=true|false
com.fasterxml.jackson.core.JsonParser.Featurespring.jackson.parser.<feature_name>=true|false
com.fasterxml.jackson.databind.SerializationFeaturespring.jackson.serialization.<feature_name>=true|false
com.fasterxml.jackson.annotation.JsonInclude.Includespring.jackson.default-property-inclusion=always|non_null|non_absent|non_default|non_empty

例如,要启用漂亮打印,请设置spring.jackson.serialization.indent_output=true。请注意,由于使用了relaxed binding,因此indent_output的情况不必与相应的枚举常量INDENT_OUTPUT的情况相匹配。

这种基于环境的配置将应用于自动配置的Jackson2ObjectMapperBuilder bean,并将应用于使用该构建器创建的任何 Map 器,包括自动配置的ObjectMapper bean。

上下文的Jackson2ObjectMapperBuilder可以由一个或多个Jackson2ObjectMapperBuilderCustomizer bean 进行自定义。可以对此类定制器 bean 进行排序,并且 Boot 自己的定制器的 Sequences 为 0,从而允许在 Boot 定制之前和之后应用其他定制。

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

如果要完全替换默认的ObjectMapper,请定义该类型的@Bean并将其标记为@Primary,或者,如果您更喜欢基于构建器的方法,请定义Jackson2ObjectMapperBuilder @Bean。请注意,无论哪种情况,这都将禁用ObjectMapper的所有自动配置。

如果您提供任何类型@Beans@Beans,则它们将替换 MVC 配置中的默认值。另外,还提供了HttpMessageConverters类型的便捷 bean(如果使用默认的 MVC 配置,则始终可用),该便捷 bean 具有一些有用的方法来访问默认的和用户增强的消息转换器。

另请参阅* 第 74.4 节“自定义@ResponseBody 渲染” *部分和WebMvcAutoConfiguration源代码以获取更多详细信息。

74.4 自定义@ResponseBody 渲染

Spring 使用HttpMessageConverters渲染@ResponseBody(或@RestController的响应)。您可以通过在 Spring Boot 上下文中简单地添加该类型的 bean 来贡献额外的转换器。如果您添加的 bean 的类型无论如何都是默认包含的(例如MappingJackson2HttpMessageConverter表示 JSON 转换),它将替换默认值。提供了HttpMessageConverters类型的便捷 bean(如果使用默认的 MVC 配置,则始终可用),该便捷 bean 具有一些有用的方法来访问默认和用户增强的消息转换器(例如,如果您想将其手动注入到自定义RestTemplate中,则很有用.)。

与普通 MVC 用法一样,您提供的任何WebMvcConfigurerAdapter bean 也可以通过重写configureMessageConverters方法来贡献转换器,但是与普通 MVC 不同,您只能提供所需的其他转换器(因为 Spring Boot 使用相同的机制来贡献其默认值)。 。最后,如果您通过提供自己的@EnableWebMvc配置选择退出 Spring Boot 默认 MVC 配置,则可以完全控制并使用WebMvcConfigurationSupport中的getMessageConverters手动进行所有操作。

有关更多详细信息,请参见WebMvcAutoConfiguration源代码。

74.5 处理分段文件上传

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

当您想在 Spring MVC 控制器处理程序方法中接收 Multipart 编码的文件数据作为@RequestParamComments 类型MultipartFile的参数时,Multipart 支持会很有帮助。

有关更多详细信息,请参见MultipartAutoConfiguration源。

74.6 关闭 Spring MVC DispatcherServlet

Spring Boot 希望从应用程序/的根目录开始提供所有内容。如果您希望将自己的 servletMap 到该 URL,则可以执行此操作,但是当然您可能会失去其他一些 Boot MVC 功能。要添加您自己的 servlet 并将其 Map 到根资源,只需声明一个类型为Servlet@Bean并为其指定特殊的 Bean 名称dispatcherServlet(如果要关闭它,也可以创建一个具有该名称的其他类型的 Bean,而不必关闭它代替它)。

74.7 关闭默认的 MVC 配置

完全控制 MVC 配置的最简单方法是为自己的@Configuration提供@EnableWebMvc注解。这将使您所有的 MVC 配置都掌握在手中。

74.8 自定义 ViewResolvers

ViewResolver是 Spring MVC 的核心组件,将@Controller中的视图名称转换为实际的View实现。请注意,ViewResolvers主要用于 UI 应用程序,而不是 REST 风格的服务(View不用于渲染@ResponseBody)。 ViewResolver的实现有很多可供选择,而 Spring 本身并未就应该使用哪个实现提出意见。另一方面,Spring Boot 根据在 Classpath 和应用程序上下文中找到的内容为您安装一两个。 DispatcherServlet使用它在应用程序上下文中找到的所有解析器,依次尝试每个解析器直到获得结果,因此,如果要添加自己的解析器,则必须知道 Sequences 以及解析器的添加位置。

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

  • Bean ID 为“ defaultViewResolver”的InternalResourceViewResolver。这是一个可以使用DefaultServlet渲染的物理资源(例如,如果使用的是静态资源和 JSP 页面)。它在视图名称中应用前缀和后缀,然后在 Servlet 上下文中查找具有该路径的物理资源(默认值均为空,但可通过spring.mvc.view.prefixspring.mvc.view.suffix进行外部配置访问)。通过提供相同类型的 bean 可以覆盖它。

  • ID 为“ beanNameViewResolver”的BeanNameViewResolver。这是视图解析器链的有用成员,它将拾取与要解析的View相同名称的所有 bean。不必重写或替换它。

  • 仅当实际上存在“ View”类型的 bean 时,才添加 ID 为“ viewResolver”的ContentNegotiatingViewResolver。这是一个“主”解析器,委派给所有其他解析器,并尝试查找与 Client 端发送的“ Accept” HTTPHeaders 匹配的内容。您可能想学习有用的关于 ContentNegotiatingViewResolver 的博客以了解更多信息,并查看源代码以获取详细信息。您可以通过定义一个名为'viewResolver'的 bean 来关闭自动配置的ContentNegotiatingViewResolver

  • 如果您使用 Thymeleaf,您还将拥有 ID 为“ thymeleafViewResolver”的ThymeleafViewResolver。它通过在视图名称前后加上前缀和后缀(分别扩展为spring.thymeleaf.prefixspring.thymeleaf.suffix,分别默认为'classpath:/ templates /'和'.html')来查找资源。可以通过提供相同名称的 bean 来覆盖它。

  • 如果您使用 FreeMarker,您还将拥有 ID 为“ freeMarkerViewResolver”的FreeMarkerViewResolver。它通过在视图名称前加上前缀和后缀(分别扩展为spring.freemarker.prefixspring.freemarker.suffix,分别为空和'.ftl)来在加载器路径(扩展为spring.freemarker.templateLoaderPath,默认为'classpath:/ templates /')中查找资源。可以通过提供相同名称的 bean 来覆盖它。

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

检出WebMvcAutoConfigurationThymeleafAutoConfigurationFreeMarkerAutoConfigurationGroovyTemplateAutoConfiguration

74.9 使用 Thymeleaf 3

默认情况下,spring-boot-starter-thymeleaf使用 Thymeleaf 2.1. 如果使用的是spring-boot-starter-parent,则可以通过覆盖thymeleaf.versionthymeleaf-layout-dialect.version属性来使用 Thymeleaf 3,例如:

<properties>
    <thymeleaf.version>3.0.2.RELEASE</thymeleaf.version>
    <thymeleaf-layout-dialect.version>2.1.1</thymeleaf-layout-dialect.version>
</properties>

Note

如果您要自己 Management 依赖关系,请查看spring-boot-dependencies以获得与这两个版本相关的工件列表。

为避免有关不赞成使用 HTML 5 模板模式而改用 HTML 模板模式的警告消息,您可能还希望将spring.thymeleaf.mode显式配置为HTML,例如:

spring.thymeleaf.mode: HTML

请参阅Thymeleaf 3samples以查看此操作。

如果您正在使用其他任何自动配置的 Thymeleaf Extras(Spring Security,Data Attribute 或 Java 8 Time),则还应将其每个版本覆盖为与 Thymeleaf 3.0 兼容的版本。