Spring MVC
Spring Boot 有许多Starters,包括 Spring MVC。 请注意,一些 starters 包含对 Spring MVC 的依赖,而不是直接包含它。 本节回答有关 Spring MVC 和 Spring Boot 的常见问题。
编写 JSON REST 服务
只要 Jackson2 在 Classpath 上,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()
}
}
只要可以被 Jackson2 序列化(对于普通的 POJO 或 Groovy 对象来说是如此),那么默认情况下会提供它的 JSON 表示。
请注意,在浏览器中,您有时可能会看到 XML 响应,因为浏览器倾向于发送首选 XML 的 accept 标头。MyThing
localhost:8080/thing
编写 XML REST 服务
如果 Classpath 上有 Jackson XML 扩展 (),则可以使用它来呈现 XML 响应。
我们用于 JSON 的上一个示例将起作用。
要使用 Jackson XML 渲染器,请将以下依赖项添加到您的项目中:jackson-dataformat-xml
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
</dependency>
如果 Jackson 的 XML 扩展不可用,而 JAXB 可用,则可以呈现 XML,但需要额外要求将 XML 注释为 @XmlRootElement
,如以下示例所示:MyThing
-
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 在 Classpath 上,则您已经获得了 Jackson2ObjectMapperBuilder
提供的默认转换器,其实例已为您自动配置。
ObjectMapper
(或 XmlMapper
for Jackson XML 转换器)实例(默认创建)具有以下自定义属性:
-
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 中)中进行了描述:
枚举 | 财产 | 值 |
---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
例如,要启用美颜打印,请将 .
请注意,由于使用了松弛绑定,case of 不必与相应的枚举常量的大小写匹配,即 。spring.jackson.serialization.indent_output=true
indent_output
INDENT_OUTPUT
这种基于环境的配置应用于自动配置的 Jackson2ObjectMapperBuilder
Bean,并应用于使用构建器创建的任何映射器,包括自动配置的 ObjectMapper
Bean。
上下文的Jackson2ObjectMapperBuilder
可以由一个或多个Jackson2ObjectMapperBuilderCustomizer
bean 进行自定义。
可以对此类定制器 bean 进行排序(Boot 自己的定制器的 order 为 0),从而允许在 Boot 的定制之前和之后应用其他定制。
任何类型为 Module
的 bean 都会自动注册到自动配置的 Jackson2ObjectMapperBuilder
中,并应用于它创建的任何 ObjectMapper
实例。
这提供了一种全局机制,用于在向应用程序添加新功能时提供自定义模块。
如果要完全替换默认的 ObjectMapper
,请定义该类型的@Bean
,或者如果您更喜欢基于构建器的方法,请定义 Jackson2ObjectMapperBuilder
@Bean
。
定义 ObjectMapper
bean 时,建议将其标记为 @Primary
,因为它将替换的自动配置的 ObjectMapper
@Primary
。
请注意,无论哪种情况,这样做都会禁用 ObjectMapper
的所有自动配置。
如果你提供任何类型为MappingJackson2HttpMessageConverter
的@Beans
,它们将替换 MVC 配置中的默认值。
此外,还提供了一个 HttpMessageConverters
类型的便捷 Bean(如果使用默认的 MVC 配置,则始终可用)。
它有一些有用的方法来访问默认和用户增强的消息转换器。
有关更多详细信息,请参阅自定义@ResponseBody渲染部分和 WebMvcAutoConfiguration
源代码。
自定义 @ResponseBody 渲染
Spring 使用 HttpMessageConverters
来呈现@ResponseBody
(或来自 @RestController
的响应)。
您可以通过在 Spring Boot 上下文中添加适当类型的 bean 来贡献其他转换器。
如果你添加的 Bean 的类型无论如何都会包含在内(例如用于 JSON 转换的MappingJackson2HttpMessageConverter
),它将替换默认值。
提供了一个 HttpMessageConverters
类型的便捷 Bean,如果您使用默认的 MVC 配置,则它始终可用。
它有一些有用的方法来访问默认和用户增强的消息转换器(例如,如果你想手动将它们注入到自定义 RestTemplate
中,它会很有用)。
与正常的 MVC 使用一样,你提供的任何 WebMvcConfigurer
bean 也可以通过覆盖该方法来提供转换器。
但是,与普通 MVC 不同的是,您只能提供所需的其他转换器(因为 Spring Boot 使用相同的机制来提供其默认值)。
最后,如果你通过提供自己的 Spring Boot MVC 配置来选择退出默认的 Spring Boot MVC 配置@EnableWebMvc
,则可以完全控制并使用WebMvcConfigurationSupport
手动完成所有操作。configureMessageConverters
getMessageConverters
有关更多详细信息,请参见WebMvcAutoConfiguration
源代码。
处理分段文件上传
Spring Boot 采用 servlet 5 Part
API 来支持上传文件。
默认情况下, Spring Boot 将 Spring MVC 配置为每个文件的最大大小为 1MB,在单个请求中的最大文件数据为 10MB。
您可以使用 MultipartProperties
类中公开的属性覆盖这些值、中间数据存储的位置(例如,存储到目录)以及将数据刷新到磁盘的阈值。
例如,如果要指定文件不受限制,请将该属性设置为 。/tmp
spring.servlet.multipart.max-file-size
-1
当你想在 Spring MVC 控制器处理程序方法中将多部分编码文件数据作为MultipartFile
类型的@RequestParam
注释参数接收时,multipart支持非常有用。
有关更多详细信息,请参阅 MultipartAutoConfiguration
源。
建议使用容器对分段上传的内置支持,而不是引入额外的依赖项,例如 Apache Commons File Upload。 |
关闭 Spring MVC DispatcherServlet
默认情况下,所有内容都从应用程序的根目录 () 提供。
如果您希望映射到其他路径,则可以按如下方式配置一个路径:/
-
Properties
-
YAML
spring.mvc.servlet.path=/mypath
spring:
mvc:
servlet:
path: "/mypath"
如果你有其他 servlet,你可以为每个 servlet 声明一个 Servlet
或 ServletRegistrationBean
类型的@Bean,Spring
Boot 会以透明的方式将它们注册到容器。
由于 Servlet 是以这种方式注册的,因此可以将它们映射到 DispatcherServlet
的子上下文,而无需调用它。
自己配置 DispatcherServlet
是不常见的,但如果您确实需要这样做,还必须提供 DispatcherServletPath
类型的@Bean
来提供自定义 DispatcherServlet
的路径。
关闭默认 MVC 配置
完全控制 MVC 配置的最简单方法是为您自己的 @Configuration
提供 @EnableWebMvc
注解。
这样做会将所有 MVC 配置都掌握在您手中。
自定义 ViewResolver
ViewResolver
是 Spring MVC 的核心组件,它将 @Controller
中的视图名称转换为实际的视图
实现。
请注意,视图解析器主要用于 UI 应用程序,而不是 REST 风格的服务(View
不用于呈现@ResponseBody
)。
ViewResolver
有许多实现可供选择,Spring 本身并不拘泥于您应该使用哪些实现。
另一方面, Spring Boot 会为您安装一两个,具体取决于它在 Classpath 和应用程序上下文中找到的内容。
DispatcherServlet
使用它在应用程序上下文中找到的所有解析器,依次尝试每个解析器,直到获得结果。
如果您添加自己的解析程序,则必须了解添加解析程序的顺序和位置。
WebMvcAutoConfiguration
将以下ViewResolver
bean 添加到你的上下文中:
-
一个名为 '
defaultViewResolver' 的 InternalResourceViewResolver
。 此 API 查找可使用 (包括静态资源和 JSP 页,如果使用它们) 呈现的物理资源。 它将前缀和后缀应用于视图名称,然后在 servlet 上下文中查找具有该路径的物理资源(默认值都为空,但可以通过 和 进行外部配置)。 您可以通过提供相同类型的 bean 来覆盖它。DefaultServlet
spring.mvc.view.prefix
spring.mvc.view.suffix
-
一个名为 'beanNameViewResolver' 的
BeanNameViewResolver
。 这是视图解析器链的一个有用成员,它拾取与正在解析的View
同名的任何 bean。 应该没有必要覆盖或替换它。 -
仅当实际存在
View
类型的 bean 时,才会添加名为 'viewResolver' 的ContentNegotiatingViewResolver
。 这是一个复合解析器,委托给所有其他解析器,并尝试查找与客户端发送的 'Accept' HTTP 标头的匹配项。 有一个关于ContentNegotiatingViewResolver
的有用博客,您可能想学习以了解更多信息,您还可以查看源代码以获取详细信息。 你可以通过定义一个名为 'viewResolver' 的 bean 来关闭自动配置的ContentNegotiatingViewResolver
。 -
如果你使用 Thymeleaf,你还有一个名为 'thymeleafViewResolver' 的
ThymeleafViewResolver
。 它通过用前缀和后缀将视图名称括起来来查找资源。 前缀为 ,后缀为 。 前缀和后缀的值分别默认为 'classpath:/templates/' 和 '.html' 。 你可以通过提供同名的 bean 来覆盖ThymeleafViewResolver
。spring.thymeleaf.prefix
spring.thymeleaf.suffix
-
如果您使用 FreeMarker,则还有一个名为 'freeMarkerViewResolver' 的
FreeMarkerViewResolver
。 它通过在视图名称周围加上前缀和后缀来查找加载器路径(该路径已外部化,默认值为 'classpath:/templates/')。 前缀外部化为 ,后缀外部化为 。 前缀和后缀的默认值分别为 empty 和 '.ftlh'。 你可以通过提供同名的 bean 来覆盖FreeMarkerViewResolver
。 可以通过定义FreeMarkerVariablesCustomizer
类型的 bean 来自定义 FreeMarker 变量。spring.freemarker.templateLoaderPath
spring.freemarker.prefix
spring.freemarker.suffix
-
如果你使用 Groovy 模板(实际上,如果你在你的 Classpath 上),你还有一个名为 'groovyMarkupViewResolver' 的
GroovyMarkupViewResolver
。 它通过在视图名称周围加上前缀和后缀(externalized to 和 )来查找加载器路径中的资源。 前缀和后缀的默认值分别为 'classpath:/templates/' 和 '.tpl'。 你可以通过提供同名的 bean 来覆盖GroovyMarkupViewResolver
。groovy-templates
spring.groovy.template.prefix
spring.groovy.template.suffix
-
如果使用 Mustache,则还有一个名为 'mustacheViewResolver' 的
MustacheViewResolver
。 它通过用前缀和后缀将视图名称括起来来查找资源。 前缀为 ,后缀为 。 前缀和后缀的值分别默认为 'classpath:/templates/' 和 '.mustache'。 你可以通过提供同名的 bean 来覆盖MustacheViewResolver
。spring.mustache.prefix
spring.mustache.suffix
有关更多详细信息,请参阅以下部分:
自定义 'whitelabel' 错误页面
Spring Boot 会安装一个“whitelabel”错误页面,如果您遇到服务器错误,您会在浏览器客户端中看到该页面(使用 JSON 和其他媒体类型的机器客户端应该看到带有正确错误代码的合理响应)。
设置为关闭默认错误页面。
这样做将恢复您正在使用的 Servlet 容器的默认值。
请注意, Spring Boot 仍然尝试解决错误视图,因此您可能应该添加自己的错误页面,而不是完全禁用它。server.error.whitelabel.enabled=false |
用您自己的页面覆盖错误页面取决于您使用的模板技术。
例如,如果使用 Thymeleaf,则可以添加模板。
如果您使用 FreeMarker,则可以添加模板。
通常,您需要一个使用 name 解析的 View
或处理路径的 @Controller
。
除非你替换了一些默认配置,否则你应该在ApplicationContext
中找到一个BeanNameViewResolver
,所以一个名为@Bean
将是实现此目的的一种方式。
有关更多选项,请参阅 ErrorMvcAutoConfiguration
。error.html
error.ftlh
error
/error
error
有关如何在 servlet 容器中注册处理程序的详细信息,另请参阅错误处理部分。