Spring Boot非常适合Web应用程序开发。您可以使用嵌入式Tomcat,Jetty,Undertow或Netty创建独立的HTTP服务器。大多数Web应用程序都使用该spring-boot-starter-web
模块来快速启动和运行。您还可以选择使用该spring-boot-starter-webflux
模块来构建反应式Web应用程序。
如果尚未开发Spring Boot Web应用程序,则可以遵循“ Hello World!”。入门部分中的示例。
7.1 “ Spring Web MVC框架”
在Spring Web MVC框架(通常被称为“Spring MVC”)是一个丰富的“模型视图控制器” Web框架。Spring MVC允许您创建特殊的@Controller
或@RestController
bean来处理传入的HTTP请求。控制器中的方法通过使用@RequestMapping
批注映射到HTTP 。
以下代码显示了@RestController
提供JSON数据的典型代码:
@RestController
@RequestMapping(value="/users")
public class MyRestController {
@RequestMapping(value="/{user}", method=RequestMethod.GET)
public User getUser(@PathVariable Long user) {
// ...
}
@RequestMapping(value="/{user}/customers", method=RequestMethod.GET)
List<Customer> getUserCustomers(@PathVariable Long user) {
// ...
}
@RequestMapping(value="/{user}", method=RequestMethod.DELETE)
public User deleteUser(@PathVariable Long user) {
// ...
}
}
Spring MVC是核心Spring Framework的一部分,有关详细信息,请参阅参考文档。在spring.io/guides上还有一些涵盖Spring MVC的指南。
7.1.1 Spring MVC自动配置
Spring Boot为Spring MVC提供了自动配置,可与大多数应用程序完美配合。
自动配置在Spring的默认值之上添加了以下功能:
- 包含
ContentNegotiatingViewResolver
和BeanNameViewResolver
。 - 支持提供静态资源,包括对WebJars的支持(在本文档的后面部分中有介绍)。
- 自动注册
Converter
,GenericConverter
和Formatter
豆类。 - 支持
HttpMessageConverters
(在本文档后面介绍)。 - 自动注册
MessageCodesResolver
(在本文档后面介绍)。 - 静态
index.html
支持。 - 自动使用
ConfigurableWebBindingInitializer
bean(在本文档后面部分中介绍)。
如果要保留这些Spring Boot MVC定制并进行更多的MVC定制(拦截器,格式化程序,视图控制器和其他功能),则可以添加自己@Configuration
的type类,WebMvcConfigurer
但不添加 @EnableWebMvc
。
如果你想提供的定制情况RequestMappingHandlerMapping
,RequestMappingHandlerAdapter
或者ExceptionHandlerExceptionResolver
,仍然保持弹簧引导MVC自定义,你可以声明类型的豆WebMvcRegistrations
,并用它来提供这些组件的定制实例。
如果你想利用Spring MVC中的完全控制,你可以添加自己的@Configuration
注解为@EnableWebMvc
,或者添加自己的@Configuration
-annotatedDelegatingWebMvcConfiguration
中的Javadoc中所述@EnableWebMvc
。
7.1.2 HttpMessageConverters
Spring MVC使用该HttpMessageConverter
接口转换HTTP请求和响应。开箱即用中包含明智的默认设置。例如,可以将对象自动转换为JSON(通过使用Jackson库)或XML(通过使用Jackson XML扩展(如果可用)或通过使用JAXB(如果Jackson XML扩展不可用))。默认情况下,字符串编码为UTF-8
。
如果需要添加或自定义转换器,则可以使用Spring Boot的HttpMessageConverters
类,如以下清单所示:
import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
import org.springframework.context.annotation.*;
import org.springframework.http.converter.*;
@Configuration(proxyBeanMethods = false)
public class MyConfiguration {
@Bean
public HttpMessageConverters customConverters() {
HttpMessageConverter<?> additional = ...
HttpMessageConverter<?> another = ...
return new HttpMessageConverters(additional, another);
}
}
HttpMessageConverter
上下文中存在的任何Bean都将添加到转换器列表中。您也可以用相同的方法覆盖默认转换器。
7.1.3 自定义JSON序列化器和反序列化器
如果使用Jackson来序列化和反序列化JSON数据,则可能需要编写自己的JsonSerializer
和JsonDeserializer
类。自定义序列化程序通常是通过模块向Jackson进行注册的,但是Spring Boot提供了一种可选的@JsonComponent
注释,使直接注册Spring Bean变得更加容易。
您可以使用@JsonComponent
直接的注解JsonSerializer
,JsonDeserializer
或KeyDeserializer
实现。您还可以在包含序列化器/反序列化器作为内部类的类上使用它,如以下示例所示:
import java.io.*;
import com.fasterxml.jackson.core.*;
import com.fasterxml.jackson.databind.*;
import org.springframework.boot.jackson.*;
@JsonComponent
public class Example {
public static class Serializer extends JsonSerializer<SomeObject> {
// ...
}
public static class Deserializer extends JsonDeserializer<SomeObject> {
// ...
}
}
中的所有@JsonComponent
bean都会ApplicationContext
自动向Jackson进行注册。因为使用@JsonComponent
进行了元注释@Component
,所以适用通常的组件扫描规则。
Spring Boot还提供了JsonObjectSerializer
和JsonObjectDeserializer
基类,它们在序列化对象时为标准Jackson版本提供了有用的替代方法。有关详细信息,请参见JsonObjectSerializer
和JsonObjectDeserializer
在Javadoc中。
7.1.4 MessageCodesResolver
Spring MVC的具有产生错误代码从绑定错误的渲染错误消息的策略:MessageCodesResolver
。如果设置spring.mvc.message-codes-resolver-format
属性PREFIX_ERROR_CODE
或POSTFIX_ERROR_CODE
,Spring Boot会为您创建一个(请参阅中的枚举DefaultMessageCodesResolver.Format
)。
7.1.5 静态内容
默认情况下,Spring Boot从类路径中名为/static
(/public
或/resources
或/META-INF/resources
)的目录或根目录提供静态内容ServletContext
。它使用ResourceHttpRequestHandler
Spring MVC中的from,因此您可以通过添加自己WebMvcConfigurer
的addResourceHandlers
方法并覆盖该方法来修改该行为。
在独立的Web应用程序中,还启用了容器中的默认servlet,并将其用作后备,从ServletContext
Spring决定不处理它的根开始提供内容。在大多数情况下,这不会发生(除非您修改默认的MVC配置),因为Spring始终可以通过处理请求DispatcherServlet
。
默认情况下,资源映射到/**
,但是您可以使用spring.mvc.static-path-pattern
属性对其进行调整。例如,将所有资源重新分配到/resources/**
以下位置即可:
物产
Properties:
spring.mvc.static-path-pattern=/resources/**
Yaml:
spring:
mvc:
static-path-pattern: "/resources/**"
您也可以使用spring.resources.static-locations
属性来自定义静态资源位置(用目录位置列表替换默认值)。根Servlet上下文路径"/"
也会自动添加为位置。
除了前面提到的“标准”静态资源位置,Webjars内容也有特殊情况。/webjars/**
如果jar文件以Webjars格式打包,则从jar文件提供带有路径的所有资源。
src/main/webapp
如果您的应用程序打包为jar,则 不要使用该目录。尽管此目录是一个通用标准,但它仅与war打包一起使用,并且如果生成jar,大多数构建工具都将其忽略。
Spring Boot还支持Spring MVC提供的高级资源处理功能,允许使用案例,例如缓存清除静态资源或对Webjars使用版本无关的URL。
要为Webjar使用与版本无关的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
。否则,所有Webjar都将解析为404
。
要使用缓存清除,以下配置为所有静态资源配置了缓存清除解决方案,从而有效地<link href="/css/spring-2a2d595e6ed9a0b24f027f2b63b134d6.css"/>
在URL中添加了内容哈希,例如,:
Properties:
spring.resources.chain.strategy.content.enabled=true
spring.resources.chain.strategy.content.paths=/**
Yaml:
spring:
web:
resources:
chain:
strategy:
content:
enabled: true
paths: "/**"
通过
ResourceUrlEncodingFilter
为Thymeleaf和FreeMarker自动配置的,可以在运行时在模板中重写资源链接。使用JSP时,您应该手动声明此过滤器。当前尚不自动支持其他模板引擎,但可以与自定义模板宏/帮助程序一起使用,也可以使用ResourceUrlProvider
。
例如,当使用JavaScript模块加载器动态加载资源时,不可以重命名文件。这就是为什么其他策略也受支持并且可以组合的原因。“固定”策略在URL中添加静态版本字符串,而不更改文件名,如以下示例所示:
物产
Yaml
spring.resources.chain.strategy.content.enabled=true
spring.resources.chain.strategy.content.paths=/**
spring.resources.chain.strategy.fixed.enabled=true
spring.resources.chain.strategy.fixed.paths=/js/lib/
spring.resources.chain.strategy.fixed.version=v12
通过这种配置,位于下面的JavaScript模块"/js/lib/"
使用固定的版本控制策略("/v12/js/lib/mymodule.js"
),而其他资源仍使用内容版本(<link href="/css/spring-2a2d595e6ed9a0b24f027f2b63b134d6.css"/>
)。
请参阅ResourceProperties
以获取更多受支持的选项。
专门的博客文章和Spring Framework的参考文档中已经对该功能进行了全面的描述。 | |
---|---|
7.1.6 欢迎页面
Spring Boot支持静态和模板欢迎页面。它首先index.html
在配置的静态内容位置中查找文件。如果找不到,则寻找index
模板。如果找到任何一个,它将自动用作应用程序的欢迎页面。
7.1.7 路径匹配和内容协商
Spring MVC可以通过查看请求路径并将其匹配到应用程序中定义的映射(例如,@GetMapping
Controller方法的注释)来将传入的HTTP请求映射到处理程序。
Spring Boot默认选择禁用后缀模式匹配,这意味着"GET /projects/spring-boot.json"
类似的请求将不会与@GetMapping("/projects/spring-boot")
映射匹配。这被认为是Spring MVC应用程序的最佳实践。过去,此功能主要用于未发送正确的“ Accept”请求标头的HTTP客户端。我们需要确保将正确的内容类型发送给客户端。如今,内容协商已变得更加可靠。
还有其他处理HTTP客户端的方法,这些方法不能始终发送正确的“ Accept”请求标头。除了使用后缀匹配,我们还可以使用查询参数来确保将诸如这样的请求"GET /projects/spring-boot?format=json"
映射到@GetMapping("/projects/spring-boot")
:
物产
Yaml
spring.mvc.contentnegotiation.favor-parameter=true
或者,如果您更喜欢使用其他参数名称:
spring:
mvc:
contentnegotiation:
favor-parameter: true
parameter-name: "myparam"
开箱即用地支持大多数标准媒体类型,但是您也可以定义新的媒体类型:
物产
Yaml
spring.mvc.contentnegotiation.media-types.markdown=text/markdown
后缀模式匹配已被弃用,并将在以后的版本中删除。如果您了解了注意事项,但仍希望您的应用程序使用后缀模式匹配,则需要以下配置:
spring.mvc.contentnegotiation.favor-path-extension=true
spring.mvc.pathmatch.use-suffix-pattern=true
另外,与其打开所有后缀模式,不如只支持注册的后缀模式,这会更安全:
物产
Yaml
spring.mvc.contentnegotiation.favor-path-extension=true
spring.mvc.pathmatch.use-registered-suffix-pattern=true
从Spring Framework 5.3开始,Spring MVC支持多种实现策略,用于将请求路径匹配到Controller处理程序。它以前仅支持该AntPathMatcher
策略,但现在也提供了PathPatternParser
。Spring Boot现在提供一个配置属性供您选择和选择新策略:
物产
Yaml
spring.mvc.pathmatch.matching-strategy=path-pattern-parser
有关为什么应考虑使用此新实现的更多详细信息,请查看 专用博客文章。
PathPatternParser 是一个优化的实施,但限制使用 一些路径图案的变体 ,并且与后缀模式匹配(不相容spring.mvc.pathmatch.use-suffix-pattern , spring.mvc.pathmatch.use-registered-suffix-pattern )或映射DispatcherServlet 与一个Servlet前缀(spring.mvc.servlet.path )。 |
|
---|---|
7.1.8 ConfigurableWebBindingInitializer
Spring MVC使用aWebBindingInitializer
来初始化WebDataBinder
特定请求。如果创建自己的ConfigurableWebBindingInitializer
@Bean
,Spring Boot会自动将Spring MVC配置为使用它。
7.1.9 模板引擎
除了REST Web服务之外,您还可以使用Spring MVC来提供动态HTML内容。Spring MVC支持多种模板技术,包括Thymeleaf,FreeMarker和JSP。同样,许多其他模板引擎包括他们自己的Spring MVC集成。
Spring Boot包括对以下模板引擎的自动配置支持:
- FreeMarker
- Groovy
- 胸腺
- 胡子 | | 如果可能,应避免使用JSP。将它们与嵌入式servlet容器一起使用时,存在几个已知的限制。 | | :—-: | —- |
在默认配置下使用这些模板引擎之一时,会自动从中提取模板src/main/resources/templates
。
根据您运行应用程序的方式,您的IDE可能对类路径进行不同的排序。与使用Maven或Gradle或从其打包的jar运行应用程序时相比,从IDE的主要方法运行应用程序的顺序会有所不同。这可能导致Spring Boot无法找到期望的模板。如果遇到此问题,可以在IDE中重新排序类路径,以首先放置模块的类和资源。 | |
---|---|
7.1.10 错误处理
默认情况下,Spring Boot提供了/error
一种可以明智地处理所有错误的映射,并且已在servlet容器中注册为“全局”错误页面。对于机器客户端,它将生成JSON响应,其中包含错误,HTTP状态和异常消息的详细信息。对于浏览器客户端,存在一个“ whitelabel”错误视图,该视图以HTML格式呈现相同的数据(要对其进行自定义,请添加View
解析为error
)。要完全替换默认行为,可以实现ErrorController
并注册该类型的Bean定义,或添加类型的BeanErrorAttributes
以使用现有机制但替换其内容。
在BasicErrorController 可以用作自定义基类ErrorController 。如果您想为新的内容类型添加处理程序(默认是text/html 专门处理并为其他所有内容提供后备功能),则此功能特别有用。为此,请扩展BasicErrorController ,添加@RequestMapping 具有produces 属性的带有的公共方法,并创建新类型的bean。 |
|
---|---|
您还可以定义带有注释的类,@ControllerAdvice
以自定义JSON文档以针对特定的控制器和/或异常类型返回,如以下示例所示:
@ControllerAdvice(basePackageClasses = AcmeController.class)
public class AcmeControllerAdvice extends ResponseEntityExceptionHandler {
@ExceptionHandler(YourException.class)
@ResponseBody
ResponseEntity<?> handleControllerException(HttpServletRequest request, Throwable ex) {
HttpStatus status = getStatus(request);
return new ResponseEntity<>(new CustomErrorType(status.value(), ex.getMessage()), status);
}
private HttpStatus getStatus(HttpServletRequest request) {
Integer statusCode = (Integer) request.getAttribute("javax.servlet.error.status_code");
if (statusCode == null) {
return HttpStatus.INTERNAL_SERVER_ERROR;
}
return HttpStatus.valueOf(statusCode);
}
}
在前面的示例中,如果ifYourException
由与相同的程序包中定义的控制器抛出,则使用POJOAcmeController
的JSON表示CustomErrorType
代替该ErrorAttributes
表示。
自定义错误页面
如果要显示给定状态代码的自定义HTML错误页面,可以将文件添加到/error
目录。错误页面可以是静态HTML(即添加到任何静态资源目录下),也可以使用模板来构建。文件名应为确切的状态代码或系列掩码。
例如,要映射404
到静态HTML文件,您的目录结构如下:
src/
+- main/
+- java/
| + <source code>
+- resources/
+- public/
+- error/
| +- 404.html
+- <other public assets>
要5xx
使用FreeMarker模板映射所有错误,您的目录结构如下:
src/
+- main/
+- java/
| + <source code>
+- resources/
+- templates/
+- error/
| +- 5xx.ftlh
+- <other templates>
对于更复杂的映射,还可以添加实现该ErrorViewResolver
接口的bean ,如以下示例所示:
public class MyErrorViewResolver implements ErrorViewResolver {
@Override
public ModelAndView resolveErrorView(HttpServletRequest request,
HttpStatus status, Map<String, Object> model) {
// Use the request or status to optionally return a ModelAndView
return ...
}
}
您还可以使用常规的Spring MVC功能,例如@ExceptionHandler
方法和@ControllerAdvice
。在ErrorController
随后拿起任何未处理的异常。
在Spring MVC之外映射错误页面
对于不使用Spring MVC的应用程序,您可以使用ErrorPageRegistrar
接口直接注册ErrorPages
。此抽象直接与基础嵌入式servlet容器一起使用,即使您没有Spring MVC也可以使用DispatcherServlet
。
@Bean
public ErrorPageRegistrar errorPageRegistrar(){
return new MyErrorPageRegistrar();
}
// ...
private static class MyErrorPageRegistrar implements ErrorPageRegistrar {
@Override
public void registerErrorPages(ErrorPageRegistry registry) {
registry.addErrorPages(new ErrorPage(HttpStatus.BAD_REQUEST, "/400"));
}
}
如果您ErrorPage 使用最终由a处理的路径注册Filter (与某些非Spring Web框架,例如Jersey和Wicket相同),则Filter 必须将其显式注册为ERROR 调度程序,如以下示例所示: |
|
---|---|
@Bean
public FilterRegistrationBean myFilter() {
FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setFilter(new MyFilter());
...
registration.setDispatcherTypes(EnumSet.allOf(DispatcherType.class));
return registration;
}
请注意,默认值FilterRegistrationBean
不包括ERROR
调度程序类型。
战争部署中的错误处理
当部署到servlet容器时,Spring Boot使用其错误页面过滤器将具有错误状态的请求转发到适当的错误页面。这是必需的,因为Servlet规范没有提供用于注册错误页面的API。根据将war文件部署到的容器以及应用程序使用的技术,可能需要一些其他配置。
如果尚未提交响应,则错误页面过滤器只能将请求转发到正确的错误页面。缺省情况下,WebSphere Application Server 8.0和更高版本在成功完成servlet的服务方法后提交响应。您应该通过设置com.ibm.ws.webcontainer.invokeFlushAfterService
为来禁用此行为false
。
如果您使用的是Spring Security,并且想访问错误页面中的主体,则必须配置Spring Security的过滤器以在错误分派时调用。为此,请将spring.security.filter.dispatcher-types
属性设置为async, error, forward, request
。
7.1.11 春季HATEOAS
如果您开发使用超媒体的RESTful API,Spring Boot将为Spring HATEOAS提供自动配置,该配置可与大多数应用程序很好地兼容。自动配置取代了使用@EnableHypermediaSupport
和注册许多Bean的需求,以简化基于超媒体的应用程序的构建,包括LinkDiscoverers
(用于客户端支持)和ObjectMapper
配置为正确地将响应编组为所需表示形式的Bean 。的ObjectMapper
是通过设置各种定制的spring.jackson.*
属性,或者,如果存在的话,通过一个Jackson2ObjectMapperBuilder
豆。
您可以使用来控制Spring HATEOAS的配置@EnableHypermediaSupport
。请注意,这样做会禁用ObjectMapper
前面所述的自定义。
7.1.12 CORS支持
跨域资源共享(CORS)是大多数浏览器实施的W3C规范,可让您灵活地指定授权哪种类型的跨域请求,而不是使用一些安全性和功能不强的方法(例如IFRAME或JSONP) 。
从4.2版本开始,Spring MVC支持CORS。在Spring Boot应用程序中使用带有注释的控制器方法CORS配置@CrossOrigin
不需要任何特定的配置。 可以通过使用自定义方法注册bean来定义全局CORS配置,如以下示例所示:WebMvcConfigurer``addCorsMappings(CorsRegistry)
@Configuration(proxyBeanMethods = false)
public class MyConfiguration {
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/api/**");
}
};
}
}
7.2 “ Spring WebFlux框架”
Spring WebFlux是Spring Framework 5.0中引入的新的响应式Web框架。与Spring MVC不同,它不需要Servlet API,是完全异步且无阻塞的,并通过Reactor项目实现Reactive Streams规范。
Spring WebFlux有两种形式:功能性的和基于注释的。基于注释的模型非常类似于Spring MVC模型,如以下示例所示:
@RestController
@RequestMapping("/users")
public class MyRestController {
@GetMapping("/{user}")
public Mono<User> getUser(@PathVariable Long user) {
// ...
}
@GetMapping("/{user}/customers")
public Flux<Customer> getUserCustomers(@PathVariable Long user) {
// ...
}
@DeleteMapping("/{user}")
public Mono<User> deleteUser(@PathVariable Long user) {
// ...
}
}
功能变体“ WebFlux.fn”将路由配置与请求的实际处理分开,如以下示例所示:
@Configuration(proxyBeanMethods = false)
public class RoutingConfiguration {
@Bean
public RouterFunction<ServerResponse> monoRouterFunction(UserHandler userHandler) {
return route(GET("/{user}").and(accept(APPLICATION_JSON)), userHandler::getUser)
.andRoute(GET("/{user}/customers").and(accept(APPLICATION_JSON)), userHandler::getUserCustomers)
.andRoute(DELETE("/{user}").and(accept(APPLICATION_JSON)), userHandler::deleteUser);
}
}
@Component
public class UserHandler {
public Mono<ServerResponse> getUser(ServerRequest request) {
// ...
}
public Mono<ServerResponse> getUserCustomers(ServerRequest request) {
// ...
}
public Mono<ServerResponse> deleteUser(ServerRequest request) {
// ...
}
}
WebFlux是Spring框架的一部分,其参考文档中提供了详细信息。
您可以根据需要定义任意数量的RouterFunction bean,以对路由器的定义进行模块化。如果需要应用优先级,可以订购Bean。 |
|
---|---|
首先,将spring-boot-starter-webflux
模块添加到您的应用程序。
在应用程序中 同时添加spring-boot-starter-web 和spring-boot-starter-webflux 模块会导致Spring Boot自动配置Spring MVC,而不是WebFlux。之所以选择这种行为,是因为许多Spring开发人员将spring-boot-starter-webflux 其添加到他们的Spring MVC应用程序中以使用反应式WebClient 。您仍然可以通过将选定的应用程序类型设置为来强制执行选择SpringApplication.setWebApplicationType(WebApplicationType.REACTIVE) 。 |
|
---|---|
7.2.1 Spring WebFlux自动配置
Spring Boot为Spring WebFlux提供了自动配置,可与大多数应用程序完美配合。
自动配置在Spring的默认值之上添加了以下功能:
- 为
HttpMessageReader
和HttpMessageWriter
实例配置编解码器(在本文档后面部分介绍)。 - 支持服务静态资源,包括对WebJars的支持(在本文档的后面部分中介绍)。
如果您想保留Spring Boot WebFlux功能并想要添加其他WebFlux配置,则可以添加自己@Configuration
的类型类,WebFluxConfigurer
但不添加 @EnableWebFlux
。
如果要完全控制Spring WebFlux,可以使用添加自己的@Configuration
注释@EnableWebFlux
。
7.2.2 带有HttpMessageReaders和HttpMessageWriters的HTTP编解码器
Spring WebFlux使用HttpMessageReader
和HttpMessageWriter
接口转换HTTP请求和响应。CodecConfigurer
通过查看类路径中可用的库,将它们配置为具有合理的默认值。
Spring Boot为编解码器提供了专用的配置属性spring.codec.*
。它还通过使用CodecCustomizer
实例来应用进一步的自定义。例如,将spring.jackson.*
配置密钥应用于Jackson编解码器。
如果需要添加或自定义编解码器,则可以创建一个自定义CodecCustomizer
组件,如以下示例所示:
import org.springframework.boot.web.codec.CodecCustomizer;
@Configuration(proxyBeanMethods = false)
public class MyConfiguration {
@Bean
public CodecCustomizer myCodecCustomizer() {
return codecConfigurer -> {
// ...
};
}
}
您还可以利用Boot的自定义JSON序列化器和反序列化器。
7.2.3 静态内容
默认情况下,Spring Boot从类路径中名为/static
(/public
或/resources
或/META-INF/resources
)的目录中提供静态内容。它使用ResourceWebHandler
Spring WebFlux中的,因此您可以通过添加自己WebFluxConfigurer
的addResourceHandlers
方法并覆盖该方法来修改该行为。
默认情况下,资源映射在上/**
,但是您可以通过设置spring.webflux.static-path-pattern
属性来对其进行调整。例如,将所有资源重新分配到/resources/**
以下位置即可:
物产
Yaml
spring.webflux.static-path-pattern=/resources/**
您还可以使用来自定义静态资源位置spring.resources.static-locations
。这样做会将默认值替换为目录位置列表。如果这样做,默认的欢迎页面检测将切换到您的自定义位置。因此,如果index.html
启动时您的任何位置都有,则为应用程序的主页。
除了前面列出的“标准”静态资源位置之外,Webjars内容也有特殊情况。/webjars/**
如果jar文件以Webjars格式打包,则从jar文件提供带有路径的所有资源。
Spring WebFlux应用程序不严格依赖Servlet API,因此不能将它们部署为war文件,也不使用src/main/webapp 目录。 |
|
---|---|
7.2.4 欢迎页面
Spring Boot支持静态和模板欢迎页面。它首先index.html
在配置的静态内容位置中查找文件。如果找不到,则寻找index
模板。如果找到任何一个,它将自动用作应用程序的欢迎页面。
7.2.5 模板引擎
除了REST Web服务之外,您还可以使用Spring WebFlux来提供动态HTML内容。Spring WebFlux支持多种模板技术,包括Thymeleaf,FreeMarker和Mustache。
Spring Boot包括对以下模板引擎的自动配置支持:
在默认配置下使用这些模板引擎之一时,会自动从中提取模板src/main/resources/templates
。
7.2.6 错误处理
Spring Boot提供了WebExceptionHandler
一个以明智的方式处理所有错误的工具。它在处理顺序中的位置紧靠WebFlux提供的处理程序之前,该处理程序被认为是最后一个。对于机器客户端,它将生成JSON响应,其中包含错误,HTTP状态和异常消息的详细信息。对于浏览器客户端,有一个“ whitelabel”错误处理程序,以HTML格式呈现相同的数据。您还可以提供自己的HTML模板来显示错误(请参阅下一节)。
定制此功能的第一步通常涉及使用现有机制,但替换或增加错误内容。为此,您可以添加类型的Bean ErrorAttributes
。
要更改错误处理行为,可以实现ErrorWebExceptionHandler
并注册该类型的Bean定义。由于aWebExceptionHandler
级别很低,因此Spring Boot还提供了一种方便的方式AbstractErrorWebExceptionHandler
,使您可以通过WebFlux功能方式处理错误,如以下示例所示:
public class CustomErrorWebExceptionHandler extends AbstractErrorWebExceptionHandler {
// Define constructor here
@Override
protected RouterFunction<ServerResponse> getRoutingFunction(ErrorAttributes errorAttributes) {
return RouterFunctions
.route(aPredicate, aHandler)
.andRoute(anotherPredicate, anotherHandler);
}
}
为了获得更完整的图像,您还可以DefaultErrorWebExceptionHandler
直接继承子类并覆盖特定的方法。
自定义错误页面
如果要显示给定状态代码的自定义HTML错误页面,可以将文件添加到/error
目录。错误页面可以是静态HTML(即添加到任何静态资源目录下),也可以使用模板构建。文件名应为确切的状态代码或系列掩码。
例如,要映射404
到静态HTML文件,您的目录结构如下:
src/
+- main/
+- java/
| + <source code>
+- resources/
+- public/
+- error/
| +- 404.html
+- <other public assets>
要5xx
使用Mustache模板映射所有错误,您的目录结构如下:
src/
+- main/
+- java/
| + <source code>
+- resources/
+- templates/
+- error/
| +- 5xx.mustache
+- <other templates>
7.2.7 网页过滤器
Spring WebFlux提供了一个WebFilter
可实现以过滤HTTP请求-响应交换的接口。 WebFilter
在应用程序上下文中找到的bean将自动用于过滤每个交换。
如果过滤器的顺序很重要,则可以使用Ordered
或对其进行注释@Order
。Spring Boot自动配置可能会为您配置Web过滤器。这样做时,将使用下表中显示的顺序:
网页过滤器 | 订购 |
---|---|
MetricsWebFilter |
Ordered.HIGHEST_PRECEDENCE + 1 |
WebFilterChainProxy (春季安全) |
-100 |
HttpTraceWebFilter |
Ordered.LOWEST_PRECEDENCE - 10 |
7.3 JAX-RS和泽西岛
如果您更喜欢REST端点的JAX-RS编程模型,则可以使用可用的实现之一来代替Spring MVC。 Jersey和Apache CXF开箱即用。CXF需要您注册其Servlet
或Filter
为@Bean
您的应用程序上下文。泽西岛(Jersey)有一些本机Spring支持,因此我们在Spring Boot中还与启动器一起为其提供了自动配置支持。
要开始使用Jersey,请将包含spring-boot-starter-jersey
为依赖项,然后需要使用一种@Bean
类型ResourceConfig
注册所有端点,如以下示例所示:
@Component
public class JerseyConfig extends ResourceConfig {
public JerseyConfig() {
register(Endpoint.class);
}
}
泽西岛对扫描可执行归档文件的支持非常有限。例如,它无法扫描在完全可执行的jar文件中或在WEB-INF/classes 运行可执行的war文件时在包中找到的端点。为避免此限制,packages 不应使用该方法,并且应使用该register 方法分别注册端点,如前面的示例所示。 |
|
---|---|
对于更高级的自定义,您还可以注册任意数量的实现的Bean ResourceConfigCustomizer
。
所有注册的端点都应@Components
带有HTTP资源注释(@GET
及其他注释),如以下示例所示:
@Component
@Path("/hello")
public class Endpoint {
@GET
public String message() {
return "Hello";
}
}
由于Endpoint
是Spring @Component
,因此其生命周期由Spring管理,您可以使用@Autowired
批注注入依赖项,并使用@Value
批注注入外部配置。默认情况下,Jersey servlet已注册并映射到/*
。您可以通过添加改变映射@ApplicationPath
到你ResourceConfig
。
默认情况下,Jersey被设置为名为@Bean
类型的Servlet 。默认情况下,该servlet延迟初始化,但是您可以通过设置来自定义该行为。您可以通过创建自己的同名bean来禁用或覆盖该bean。您还可以通过设置使用过滤器而不是servlet (在这种情况下,要替换或覆盖的是)。过滤器具有,您可以使用设置。通过使用指定属性映射,可以为servlet和过滤器注册都赋予init参数。ServletRegistrationBean``jerseyServletRegistration``spring.jersey.servlet.load-on-startup``spring.jersey.type=filter``@Bean``jerseyFilterRegistration``@Order``spring.jersey.filter.order``spring.jersey.init.*
7.4 嵌入式Servlet容器支持
Spring Boot包含对嵌入式Tomcat,Jetty和Undertow服务器的支持。大多数开发人员使用适当的“启动器”来获取完全配置的实例。默认情况下,嵌入式服务器在port上侦听HTTP请求8080
。
7.4.1 Servlet,过滤器和侦听器
使用嵌入式Servlet容器时,您可以HttpSessionListener
使用Spring Bean或扫描Servlet组件来注册Servlet规范中的Servlet,过滤器和所有侦听器(例如)。
将Servlet,过滤器和侦听器注册为Spring Bean
作为Spring bean的任何Servlet
,Filter
或servlet*Listener
实例都向嵌入式容器注册。如果要application.properties
在配置过程中引用一个值,这将特别方便。
默认情况下,如果上下文仅包含单个Servlet,则将其映射到/
。如果有多个servlet bean,则将bean名称用作路径前缀。过滤器映射到/*
。
如果以公约为基础测绘不够灵活,你可以使用ServletRegistrationBean
,FilterRegistrationBean
以及ServletListenerRegistrationBean
类的完全控制。
通常可以使无序滤豆处于安全状态。如果需要一个特定的顺序,你应该注释Filter
用@Order
或使其实现Ordered
。您无法Filter
通过使用注释a的bean方法来配置其顺序@Order
。如果您不能更改Filter
要添加@Order
或实现的类Ordered
,则必须为定义一个FilterRegistrationBean
,Filter
并使用setOrder(int)
方法设置注册bean的顺序。避免配置一个在处读取请求正文的过滤器Ordered.HIGHEST_PRECEDENCE
,因为它可能与应用程序的字符编码配置不符。如果Servlet过滤器包装了请求,则应以小于或等于的顺序对其进行配置OrderedFilter.REQUEST_WRAPPER_FILTER_MAX_ORDER
。
要查看Filter 应用程序中每个组件的顺序,请为web 日志记录组(logging.level.web=debug )启用调试级别的日志记录。然后,将在启动时记录已注册过滤器的详细信息,包括其顺序和URL模式。 |
|
---|---|
注册Filter bean时要小心,因为它们是在应用程序生命周期中很早就初始化的。如果需要注册一个Filter 与其他bean交互的对象,请考虑使用a DelegatingFilterProxyRegistrationBean 。 |
|
---|---|
7.4.2 Servlet上下文初始化
嵌入式Servlet容器不会直接执行Servlet 3.0+javax.servlet.ServletContainerInitializer
接口或Spring的org.springframework.web.WebApplicationInitializer
接口。这是一个有意设计的决定,旨在降低设计用于在战争中运行的第三方库可能破坏Spring Boot应用程序的风险。
如果您需要在Spring Boot应用程序中执行servlet上下文初始化,则应该注册一个实现该org.springframework.boot.web.servlet.ServletContextInitializer
接口的bean 。单一onStartup
方法提供对的访问,ServletContext
并且在必要时可以轻松地用作现有的适配器WebApplicationInitializer
。
扫描Servlet,过滤器和侦听器
当使用嵌入式容器中,类自动登记注释有@WebServlet
,@WebFilter
和@WebListener
可以通过使用被使能@ServletComponentScan
。
@ServletComponentScan 在独立容器中无效,而是使用容器的内置发现机制。 |
|
---|---|
7.4.3 ServletWebServerApplicationContext
在后台,Spring BootApplicationContext
对嵌入式servlet容器使用了不同类型的支持。该ServletWebServerApplicationContext
是一种特殊类型的WebApplicationContext
通过搜索单说引导自身ServletWebServerFactory
豆。通常是TomcatServletWebServerFactory
,JettyServletWebServerFactory
或UndertowServletWebServerFactory
已自动配置。
通常,您不需要了解这些实现类。大多数应用程序都自动配置,并适当的ApplicationContext 和ServletWebServerFactory 以您的名义创建。 |
|
---|---|
7.4.4 自定义嵌入式Servlet容器
可以使用SpringEnvironment
属性来配置常见的servlet容器设置。通常,您将在application.properties
或application.yaml
文件中定义属性。
常用服务器设置包括:
- 网络设置:侦听传入HTTP请求的端口(
server.port
),绑定到的接口地址server.address
,等等。 - 会话设置:会话是否为持久(
server.servlet.session.persistent
),会话超时(server.servlet.session.timeout
),会话数据位置(server.servlet.session.store-dir
)和会话cookie配置(server.servlet.session.cookie.*
)。 - 错误管理:错误页面的位置(
server.error.path
),依此类推。 - SSL协议
- HTTP压缩
Spring Boot尝试尽可能多地公开通用设置,但这并不总是可能的。在这种情况下,专用名称空间提供服务器特定的自定义(请参阅server.tomcat
和server.undertow
)。例如,可以使用嵌入式servlet容器的特定功能配置访问日志。
有关ServerProperties 完整列表,请参见课程。 |
|
---|---|
程序化定制
如果需要以编程方式配置嵌入式servlet容器,则可以注册一个实现该WebServerFactoryCustomizer
接口的Spring bean 。 WebServerFactoryCustomizer
提供对的访问ConfigurableServletWebServerFactory
,其中包括许多自定义设置方法。以下示例显示以编程方式设置端口:
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory;
import org.springframework.stereotype.Component;
@Component
public class CustomizationBean implements WebServerFactoryCustomizer<ConfigurableServletWebServerFactory> {
@Override
public void customize(ConfigurableServletWebServerFactory server) {
server.setPort(9000);
}
}
TomcatServletWebServerFactory ,JettyServletWebServerFactory 和UndertowServletWebServerFactory 是的专用变体ConfigurableServletWebServerFactory 具有用于分别的Tomcat,码头和暗流额外定制setter方法。 |
|
---|---|
直接自定义ConfigurableServletWebServerFactory
如果前面的定制技术太有限,你可以注册TomcatServletWebServerFactory
,JettyServletWebServerFactory
或UndertowServletWebServerFactory
豆你自己。
@Bean
public ConfigurableServletWebServerFactory webServerFactory() {
TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory();
factory.setPort(9000);
factory.setSessionTimeout(10, TimeUnit.MINUTES);
factory.addErrorPages(new ErrorPage(HttpStatus.NOT_FOUND, "/notfound.html"));
return factory;
}
提供了许多配置选项的设置器。如果您需要做一些更奇特的操作,还提供了几种受保护的方法“挂钩”。有关详细信息,请参见源代码文档。
7.4.5 JSP局限性
当运行使用嵌入式Servlet容器(并打包为可执行档案)的Spring Boot应用程序时,JSP支持存在一些限制。
- 对于Jetty和Tomcat,如果使用战争包装,它应该可以工作。与一起启动时
java -jar
,可执行的War将起作用,并且还将可部署到任何标准容器中。使用可执行jar时,不支持JSP。 - Undertow不支持JSP。
创建自定义
error.jsp
页面不会覆盖默认视图以进行错误处理。 应改用自定义错误页面。7.5 嵌入式反应服务器支持
Spring Boot包含对以下嵌入式反应式Web服务器的支持:Reactor Netty,Tomcat,Jetty和Undertow。大多数开发人员使用适当的“启动器”来获取完全配置的实例。默认情况下,嵌入式服务器在端口8080上侦听HTTP请求。
7.6 反应性服务器资源配置
在自动配置Reactor Netty或Jetty服务器时,Spring Boot将创建特定的bean,这些bean将向服务器实例提供HTTP资源:
ReactorResourceFactory
或JettyResourceFactory
。
默认情况下,在以下情况下,这些资源还将与Reactor Netty和Jetty客户端共享,以实现最佳性能:服务器和客户端使用相同的技术
- 客户端实例是使用
WebClient.Builder
Spring Boot自动配置的bean构建的
通过提供一个自定义ReactorResourceFactory
或JettyResourceFactory
bean,开发人员可以覆盖Jetty和Reactor Netty的资源配置-这将同时应用于客户端和服务器。
您可以在WebClient Runtime部分中了解有关客户端资源配置的更多信息。