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