Spring Boot对Servlet web应用的支持
https://docs.spring.io/spring-boot/docs/3.2.0/reference/htmlsingle/#web.servlet
Spring Web MVC 框架
Spring Web MVC 框架(通常称为“Spring MVC”)是一个功能丰富的“模型 视图 控制器”Web 框架。Spring MVC 允许你创建特殊的 @Controller 或 @RestController bean 来处理传入的 HTTP 请求。控制器中的方法通过使用 @RequestMapping 注解映射到 HTTP。
以下代码展示了一个典型的 @RestController,它提供 JSON 数据:
import java.util.List; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("/users") public class MyRestController { private final UserRepository userRepository; private final CustomerRepository customerRepository; public MyRestController(UserRepository userRepository, CustomerRepository customerRepository) { this.userRepository = userRepository; this.customerRepository = customerRepository; } @GetMapping("/{userId}") public User getUser(@PathVariable Long userId) { return this.userRepository.findById(userId).get(); } @GetMapping("/{userId}/customers") public List getUserCustomers(@PathVariable Long userId) { return this.userRepository.findById(userId).map(this.customerRepository::findByUser).get(); } @DeleteMapping("/{userId}") public void deleteUser(@PathVariable Long userId) { this.userRepository.deleteById(userId); } }
“WebMvc.fn”是一个功能变体,它将路由配置与实际处理请求的操作分开,如下所示:
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.MediaType; import org.springframework.web.servlet.function.RequestPredicate; import org.springframework.web.servlet.function.RouterFunction; import org.springframework.web.servlet.function.ServerResponse; import static org.springframework.web.servlet.function.RequestPredicates.accept; import static org.springframework.web.servlet.function.RouterFunctions.route; @Configuration(proxyBeanMethods = false) public class MyRoutingConfiguration { private static final RequestPredicate ACCEPT_JSON = accept(MediaType.APPLICATION_JSON); @Bean public RouterFunction routerFunction(MyUserHandler userHandler) { return route() .GET("/{user}", ACCEPT_JSON, userHandler::getUser) .GET("/{user}/customers", ACCEPT_JSON, userHandler::getUserCustomers) .DELETE("/{user}", ACCEPT_JSON, userHandler::deleteUser) .build(); } }
import org.springframework.stereotype.Component; import org.springframework.web.servlet.function.ServerRequest; import org.springframework.web.servlet.function.ServerResponse; @Component public class MyUserHandler { public ServerResponse getUser(ServerRequest request) { ... return ServerResponse.ok().build(); } public ServerResponse getUserCustomers(ServerRequest request) { ... return ServerResponse.ok().build(); } public ServerResponse deleteUser(ServerRequest request) { ... return ServerResponse.ok().build(); } }
Spring MVC 是 Spring 框架的核心部分。
提示:可以根据需要定义任意数量的 RouterFunction bean 来模块化路由器的定义。如果需要应用优先级,可以对 bean 进行排序。
Spring MVC 自动配置
Spring Boot 为 Spring MVC 提供了自动配置,这对于大多数应用程序而言非常有用。它取代了使用 @EnableWebMvc 的需求,并且这两个不能一起使用。除了 Spring MVC 的默认设置外,自动配置还提供了以下功能:
- 包含 ContentNegotiatingViewResolver 和 BeanNameViewResolver bean。
- 支持提供静态资源,包括支持 WebJars。
- 自动注册 Converter、GenericConverter 和 Formatter bean。
- 支持 HttpMessageConverters。
- 自动注册 MessageCodesResolver。
- 支持静态的 index.html。
- 自动使用 ConfigurableWebBindingInitializer bean。
如果你想保留这些 Spring Boot MVC 自定义,并进行更多 MVC 自定义(例如拦截器、格式化程序、视图控制器和其它功能),则可以添加你自己的类型为 WebMvcConfigurer 的 @Configuration 类,但不使用 @EnableWebMvc。
如果你想提供 RequestMappingHandlerMapping、RequestMappingHandlerAdapter 或 ExceptionHandlerExceptionResolver 的自定义实例,同时仍保留 Spring Boot MVC 的自定义设置,则可以声明一个类型为 WebMvcRegistrations 的 bean,并使用它来提供这些组件的自定义实例。这些自定义实例将接受 Spring MVC 的进一步初始化和配置。如果要参与(且希望)覆盖后续的处理,则应该使用 WebMvcConfigurer。
如果你不想使用自动配置,并希望完全控制 Spring MVC,请添加你自己的带有 @EnableWebMvc 注解的 @Configuration。另外,也可以添加你自己的带有 @Configuration 注解的 DelegatingWebMvcConfiguration。
Spring MVC 转换服务(Conversion Service)
Spring MVC 使用的 ConversionService 与用于从 application.properties 或 application.yaml 文件中转换值的 ConversionService 不同。这意味着 Period、Duration 和 DataSize 转换器不可用,并且 @DurationUnit 和 @DataSizeUnit 注解将被忽略。
如果你想自定义 Spring MVC 使用的 ConversionService,可以提供一个带有 addFormatters 方法的 WebMvcConfigurer bean。从该方法中,你可以注册任何你喜欢的转换器,或者可以委托给 ApplicationConversionService 上可用的静态方法。
还可以使用 spring.mvc.format.* 配置属性来定制转换。如果未进行配置,则使用以下默认值:
HttpMessageConverters
Spring MVC 使用 HttpMessageConverter 接口来转换 HTTP 请求和响应。它提供了合理的默认设置。例如,对象可以自动转换为 JSON(通过使用 Jackson 库)或 XML(如果可用,则使用 Jackson XML 扩展,否则使用 JAXB)。默认情况下,字符串以 UTF-8 编码。
如果你需要添加或自定义转换器,可以使用 Spring Boot 的 HttpMessageConverters 类,如下所示:
import org.springframework.boot.autoconfigure.http.HttpMessageConverters; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.converter.HttpMessageConverter; @Configuration(proxyBeanMethods = false) public class MyHttpMessageConvertersConfiguration { @Bean public HttpMessageConverters customConverters() { HttpMessageConverter additional = new AdditionalHttpMessageConverter(); HttpMessageConverter another = new AnotherHttpMessageConverter(); return new HttpMessageConverters(additional, another); } }
上下文中存在的任何 HttpMessageConverter bean 都会被添加到转换器列表中。你也可以用相同的方式覆盖默认转换器。
MessageCodesResolver
Spring MVC 有一个用于从绑定错误中生成错误代码以呈现错误消息的策略:MessageCodesResolver。如果你设置了 spring.mvc.message-codes-resolver-format 属性为 PREFIX_ERROR_CODE 或 POSTFIX_ERROR_CODE,Spring Boot 将为您创建一个。
静态内容
默认情况下,Spring Boot 从类路径中的名为 /static(或 /public 或 /resources 或 /META-INF/resources)的目录或从 ServletContext 的根目录中提供静态内容。它使用 Spring MVC 的 ResourceHttpRequestHandler,因此你可以通过添加自己的 WebMvcConfigurer 并覆盖 addResourceHandlers 方法来修改该行为。
在独立的 Web 应用程序中,容器中的默认 servlet 未启用。可以通过使用 server.servlet.register-default-servlet 属性来启用它。
默认 servlet 作为回退机制,如果 Spring 决定不处理它,则从 ServletContext 的根目录提供内容。在大多数情况下,这不会发生(除非你修改了默认的 MVC 配置),因为 Spring 总是可以通过 DispatcherServlet 处理请求。
默认情况下,资源映射到 /**,但你可以使用 spring.mvc.static-path-pattern 属性进行调整。例如,将所有资源重新定位到 /resources/**可以按照以下方式实现:
spring.mvc.static-path-pattern=/resources/**
你还可以使用 spring.web.resources.static-locations 属性自定义静态资源位置(用目录位置的列表替换默认值)。Servlet 上下文的根路径,“/”,也将自动作为位置添加。
除了前面提到的“标准”静态资源位置外,还对 Webjars 内容进行了特殊处理。默认情况下,如果以 Webjars 格式打包,则任何路径为 /webjars/** 的资源都从 jar 文件中提供。可以使用 spring.mvc.webjars-path-pattern 属性自定义路径。
提示:如果你的应用程序被打包为 jar 文件,请不要使用 src/main/webapp 目录。尽管此目录是一个常见的标准,但它仅适用于 war 打包,并且如果你生成 jar 文件,大多数构建工具都会静默忽略它。
Spring Boot 还支持 Spring MVC 提供的高级资源处理功能,允许使用诸如打破缓存的静态资源或使用 Webjars 的无版本 URL 等。
要使用 Webjars 的无版本 URL,请添加 webjars-locator-core 依赖项。然后声明你的 Webjar。以 jQuery 为例,添加 “/webjars/jquery/jquery.min.js” 将导致 “/webjars/jquery/x.y.z/jquery.min.js”,其中 x.y.z 是 Webjar 版本。
注意:如果你使用 JBoss,则需要声明 webjars-locator-jboss-vfs 依赖项,而不是 webjars-locator-core。否则,所有 Webjars 都将解析为 404。
要使用缓存打破功能,以下配置为所有静态资源配置了缓存打破解决方案,有效地在 URL 中添加了一个内容哈希,例如