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 中默认提供),并附加要求将MyThing
Comments 为@XmlRootElement
:
@XmlRootElement
public class MyThing {
private String name;
// .. getters and setters
}
要使服务器渲染 XML 而不是 JSON,您可能必须发送Accept: text/xml
Headers(或使用浏览器)。
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 还具有一些功能,可以更轻松地自定义此行为。
您可以使用环境配置ObjectMapper
和XmlMapper
实例。Jackson 提供了一套广泛的简单的开/关功能,可用于配置其处理的各个方面。在 Jackson 的六个枚举中描述了这些功能,这些枚举 Map 到环境中的属性:
Jackson enum | Environment property |
---|---|
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 | spring.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 编码的文件数据作为@RequestParam
Comments 类型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.prefix
和spring.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.prefix
和spring.thymeleaf.suffix
,分别默认为'classpath:/ templates /'和'.html')来查找资源。可以通过提供相同名称的 bean 来覆盖它。 -
如果您使用 FreeMarker,您还将拥有 ID 为“ freeMarkerViewResolver”的
FreeMarkerViewResolver
。它通过在视图名称前加上前缀和后缀(分别扩展为spring.freemarker.prefix
和spring.freemarker.suffix
,分别为空和'.ftl)来在加载器路径(扩展为spring.freemarker.templateLoaderPath
,默认为'classpath:/ templates /')中查找资源。可以通过提供相同名称的 bean 来覆盖它。 -
如果您使用 Groovy 模板(实际上,如果您的 Classpath 上有 groovy-templates),您还将拥有一个
GroovyMarkupViewResolver
,其 ID 为'groovyMarkupViewResolver'。它通过在视图名称前加上前缀和后缀(分别扩展为spring.groovy.template.prefix
和spring.groovy.template.suffix
,分别默认为'classpath:/ templates /'和'.tpl')来在加载器路径中查找资源。可以通过提供相同名称的 bean 来覆盖它。
检出WebMvcAutoConfiguration,ThymeleafAutoConfiguration,FreeMarkerAutoConfiguration和GroovyTemplateAutoConfiguration
74.9 使用 Thymeleaf 3
默认情况下,spring-boot-starter-thymeleaf
使用 Thymeleaf 2.1. 如果使用的是spring-boot-starter-parent
,则可以通过覆盖thymeleaf.version
和thymeleaf-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 兼容的版本。