|
如需获取最新稳定版本,请使用 Spring Boot 4.0.4! |
Spring MVC
Spring Boot 包含多个Starters,其中包含 Spring MVC。 请注意,某些Starters包含对 Spring MVC 的依赖,而不是直接包含它。 本节回答了关于 Spring MVC 和 Spring Boot 的常见问题。
编写 JSON REST 服务
只要类路径中存在 Jackson2,Spring Boot 应用程序中的任何 Spring @RestController 默认都应呈现 JSON 响应,如下例所示:
-
Java
-
Kotlin
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class MyController {
@RequestMapping("/thing")
public MyThing thing() {
return new MyThing();
}
}
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController
@RestController
class MyController {
@RequestMapping("/thing")
fun thing(): MyThing {
return MyThing()
}
}
只要 MyThing 可以被 Jackson2 序列化(对于普通的 POJO 或 Groovy 对象而言为真),那么默认情况下,localhost:8080/thing 会提供其 JSON 表示形式。
请注意,在浏览器中,您有时会看到 XML 响应,因为浏览器倾向于发送偏好 XML 的 accept 头。
编写 XML REST 服务
如果您的类路径上有 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 可用,则可以通过额外要求将 MyThing 注解为 @XmlRootElement 来渲染 XML,如下例所示:
-
Java
-
Kotlin
import jakarta.xml.bind.annotation.XmlRootElement;
@XmlRootElement
public class MyThing {
private String name;
// getters/setters ...
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
}
import jakarta.xml.bind.annotation.XmlRootElement
@XmlRootElement
class MyThing {
var name: String? = null
}
您需要确保 JAXB 库是项目的一部分,例如通过添加:
<dependency>
<groupId>org.glassfish.jaxb</groupId>
<artifactId>jaxb-runtime</artifactId>
</dependency>
要让服务器渲染 XML 而不是 JSON,您可能需要发送一个 Accept: text/xml 头信息(或使用浏览器)。 |
自定义 Jackson ObjectMapper
Spring MVC(客户端和服务器端)使用 HttpMessageConverters 来协商 HTTP 交换中的内容转换。
如果 Jackson 在类路径上,你将直接获得由 Jackson2ObjectMapperBuilder 提供的默认转换器,其实例已为你自动配置。
ObjectMapper(或用于 Jackson XML 转换器的 XmlMapper)实例(默认创建)具有以下自定义属性:
-
MapperFeature.DEFAULT_VIEW_INCLUSION已禁用 -
DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES已禁用 -
SerializationFeature.WRITE_DATES_AS_TIMESTAMPS已禁用 -
SerializationFeature.WRITE_DURATIONS_AS_TIMESTAMPS已禁用
Spring Boot 还提供了一些功能,以便更轻松地自定义此行为。
您可以使用环境配置 ObjectMapper 和 XmlMapper 实例。
Jackson 提供了一套丰富的开/关功能,可用于配置其处理的各个方面。
这些功能在 Jackson 的几个枚举中进行了描述,并映射到环境中的属性:
| 枚举 | 属性 | 值 |
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
例如,要启用美化输出,请设置 spring.jackson.serialization.indent_output=true。
请注意,由于使用了 宽松绑定,indent_output 的大小写不需要与相应的枚举常量的大小写匹配,该常量是 INDENT_OUTPUT。
此基于环境的配置应用于自动配置的 Jackson2ObjectMapperBuilder Bean,并适用于使用构建器创建的任何映射器,包括自动配置的 ObjectMapper Bean。
上下文的 Jackson2ObjectMapperBuilder 可以通过一个或多个 Jackson2ObjectMapperBuilderCustomizer Bean 进行自定义。
此类定制器 Bean 可以排序(Boot 自身的定制器顺序为 0),从而允许在 Boot 的定制之前和之后应用额外的定制。
任何类型为 Module 的 Bean 都会自动注册到自动配置的 Jackson2ObjectMapperBuilder 中,并应用于其创建的任何 ObjectMapper 实例。
这为在向应用程序添加新功能时贡献自定义模块提供了一种全局机制。
如果您希望使用 Jackson2ObjectMapperBuilderCustomizer 以编程方式注册其他模块,请确保使用接受 Consumer 的 modulesToInstall 方法,因为其他变体不具备累加性。 |
如果您想完全替换默认的 ObjectMapper,可以定义一个该类型的 @Bean,或者,如果您更喜欢基于构建器的方法,则定义一个 Jackson2ObjectMapperBuilder @Bean。
在定义 ObjectMapper Bean 时,建议将其标记为 @Primary,因为自动配置中将被其替换的 ObjectMapper 是 @Primary。
请注意,在任何一种情况下,这样做都会禁用 ObjectMapper 的所有自动配置。
如果您提供任何类型为 @Bean 的 MappingJackson2HttpMessageConverter,它们将替换 MVC 配置中的默认值。
此外,还提供了一个类型为 HttpMessageConverters 的便捷 bean(如果您使用默认的 MVC 配置,则该 bean 始终可用)。
它提供了一些有用的方法来访问默认的和用户增强的消息转换器。
查看 自定义 @ResponseBody 渲染 部分和 WebMvcAutoConfiguration 源代码以获取更多信息。
自定义 @ResponseBody 渲染
Spring 使用 HttpMessageConverters 来渲染 @ResponseBody(或来自 @RestController 的响应)。
你可以通过在 Spring Boot 上下文中添加适当类型的 bean 来贡献额外的转换器。
如果你添加的 bean 类型是默认情况下本就会包含的类型(例如用于 JSON 转换的 MappingJackson2HttpMessageConverter),它将替换默认值。
系统提供了一个类型为 HttpMessageConverters 的便捷 bean,如果你使用默认的 MVC 配置,该 bean 始终可用。
它提供了一些有用的方法来访问默认和用户增强的消息转换器(例如,如果你想将它们手动注入到自定义的 RestTemplate 中,这会很有用)。
如同在常规MVC用法中一样,您提供的任何 WebMvcConfigurer beans 也可以通过覆盖 configureMessageConverters 方法来贡献转换器。
但是,与常规MVC不同的是,您只需提供所需的额外转换器(因为Spring Boot使用相同的机制来提供其默认值)。
最后,如果您通过提供自己的 @EnableWebMvc 配置来选择退出默认的Spring Boot MVC配置,那么您可以完全掌控并手动完成所有操作,方法是使用 getMessageConverters 从 WebMvcConfigurationSupport 中获取。
请参阅 WebMvcAutoConfiguration 源代码以获取更多详细信息。
处理多部分文件上传
Spring Boot 采用 Servlet 5 Part API 来支持文件上传。
默认情况下,Spring Boot 配置 Spring MVC 每个文件的最大大小为 1MB,单个请求中文件数据的最大总大小为 10MB。
您可以覆盖这些值、中间数据存储的位置(例如,存储到 /tmp 目录),以及数据刷新到磁盘的阈值,方法是使用 MultipartProperties 类中公开的属性。
例如,如果您希望指定文件大小不受限制,请将 spring.servlet.multipart.max-file-size 属性设置为 -1。
当您希望在 Spring MVC 控制器处理方法中接收多部分编码的文件数据作为 @RequestParam 注解的 MultipartFile 类型参数时,多部分支持非常有用。
请参阅 MultipartAutoConfiguration 源代码以获取更多详细信息。
| 建议使用容器内置的多部分上传支持,而不是引入额外的依赖项(如 Apache Commons File Upload)。 |
关闭 Spring MVC DispatcherServlet
默认情况下,所有内容都从应用程序的根路径(/)提供。
如果您希望映射到其他路径,可以按如下方式进行配置:
-
Properties
-
YAML
spring.mvc.servlet.path=/mypath
spring:
mvc:
servlet:
path: "/mypath"
如果您有其他servlet,可以为每个servlet声明一个类型为@Bean或Servlet的ServletRegistrationBean,Spring Boot会将它们透明地注册到容器中。
也可以使用@ServletRegistration作为ServletRegistrationBean的基于注解的替代方案。
由于以这种方式注册了servlet,它们可以映射到DispatcherServlet的子上下文,而无需调用它。
自行配置 DispatcherServlet 并不常见,但如果确实需要这样做,则还必须提供一个类型为 DispatcherServletPath 的 @Bean,以提供自定义 DispatcherServlet 的路径。
关闭默认的 MVC 配置
控制MVC配置最简单的方法是提供您自己的 @Configuration 并使用 @EnableWebMvc 注解。
这样做的结果是将所有MVC配置交由您自己处理。
自定义 ViewResolvers
ViewResolver 是 Spring MVC 的核心组件,负责将 @Controller 中的视图名称转换为实际的 View 实现。
请注意,视图解析器主要用于 UI 应用程序,而不是 REST 风格的服务(View 不用于渲染 @ResponseBody)。
有许多 ViewResolver 的实现可供选择,Spring 本身对于应该使用哪种实现并没有强制偏好。
另一方面,Spring Boot 会根据它在类路径和应用程序上下文中发现的内容,为您安装一个或两个视图解析器。
DispatcherServlet 会使用它在应用程序上下文中找到的所有解析器,依次尝试每个解析器,直到获得结果。
如果您添加自己的解析器,必须注意顺序以及您的解析器被添加的位置。
WebMvcAutoConfiguration 向您的上下文中添加以下 ViewResolver Bean:
-
一个名为“defaultViewResolver”的
InternalResourceViewResolver。 它定位可以使用DefaultServlet渲染的物理资源(包括静态资源和 JSP 页面,如果您使用它们的话)。 它为视图名称应用前缀和后缀,然后在 Servlet 上下文中查找具有该路径的物理资源(默认值均为空,但可以通过spring.mvc.view.prefix和spring.mvc.view.suffix进行外部配置访问)。 您可以通过提供相同类型的 bean 来覆盖它。 -
一个名为‘beanNameViewResolver’的
BeanNameViewResolver。 这是视图解析器链中的一个有用成员,它会查找与正在解析的View同名的任何 bean。 通常不需要覆盖或替换它。 -
一个名为‘viewResolver’的
ContentNegotiatingViewResolver仅在实际上存在类型为View的 bean 时才会被添加。 这是一个组合解析器,会将请求委托给其他所有解析器,并尝试根据客户端发送的“Accept”HTTP头找到匹配项。 有一篇有用的 博客关于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。 可以通过定义类型为FreeMarkerVariablesCustomizer的 bean 来自定义 FreeMarker 变量。 -
如果您使用 Groovy 模板(实际上,如果
groovy-templates在您的类路径中),您还会有一个名为 ‘groovyMarkupViewResolver’ 的GroovyMarkupViewResolver。 它通过在视图名称前后添加前缀和后缀(外部化为spring.groovy.template.prefix和spring.groovy.template.suffix)在加载器路径中查找资源。 前缀和后缀的默认值分别为 ‘classpath:/templates/’ 和 ‘.tpl’。 您可以通过提供同名的 bean 来覆盖GroovyMarkupViewResolver。 -
如果您使用 Mustache,您还会有一个名为‘mustacheViewResolver’的
MustacheViewResolver。 它通过在视图名称前后添加前缀和后缀来查找资源。 前缀是spring.mustache.prefix,后缀是spring.mustache.suffix。 前缀和后缀的默认值分别为‘classpath:/templates/’和‘.mustache’。 您可以通过提供同名的 bean 来覆盖MustacheViewResolver。
有关更多详细信息,请参阅以下部分:
自定义“whitelabel”错误页面
Spring Boot 安装了一个“whitelabel”错误页面,当遇到服务器错误时,您会在浏览器客户端中看到该页面(使用 JSON 和其他媒体类型的机器客户端应看到具有正确错误代码的合理响应)。
将 server.error.whitelabel.enabled=false 设置为关闭默认错误页面。
这样做会恢复您正在使用的 Servlet 容器的默认设置。
请注意,Spring Boot 仍然尝试解析错误视图,因此您可能应该添加自己的错误页面,而不是完全禁用它。 |
使用您自己的错误页面覆盖默认错误页面取决于您使用的模板技术。
例如,如果您使用 Thymeleaf,您可以添加一个 error.html 模板。
如果您使用 FreeMarker,您可以添加一个 error.ftlh 模板。
通常,您需要一个解析名称为 error 的 View,或者一个处理 /error 路径的 @Controller。
除非您替换了某些默认配置,否则您应该在 ApplicationContext 中找到一个 BeanNameViewResolver,因此名为 error 的 @Bean 是实现此目的的一种方法。
请参阅 ErrorMvcAutoConfiguration 以了解更多选项。
有关如何在servlet容器中注册处理程序的详细信息,请参阅< a t="C0">错误处理部分。