开发Web应用程序

Spring Boot非常适合Web应用程序开发。您可以使用嵌入式Tomcat,Jetty,Undertow或Netty创建自包含的HTTP服务器。大多数Web应用程序使用该spring-boot-starter-web模块快速启动和运行。您还可以选择使用该spring-boot-starter-webflux模块构建响应式Web应用程序 。

如果您还没有开发Spring Boot Web应用程序,可以按照“Hello World!”进行操作。“ 入门”部分中的示例 。

Spring Web MVC框架

SpringWeb MVC框架(通常简称为“SpringMVC”)是一个丰富的“模型视图控制器” Web框架。Spring MVC允许您创建特殊@Controller@RestControllerbean来处理传入的HTTP请求。控制器中的方法通过使用@RequestMapping注释映射到HTTP 。

以下代码显示了@RestController为JSON数据提供服务的典型代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@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 MVC中提供一些指南spring.io/guides

Spring MVC自动配置

Spring Boot为Spring MVC提供自动配置,适用于大多数应用程序。

自动配置在Spring的默认值之上添加了以下功能:

如果您想保留Spring Boot MVC功能并且想要添加其他 MVC配置(拦截器,格式化程序,视图控制器和其他功能),您可以添加自己的@Configuration类类型WebMvcConfigurer不需要 @EnableWebMvc。如果您希望提供,或的 自定义实例RequestMappingHandlerMapping,则可以声明 实例以提供此类组件。RequestMappingHandlerAdapter`ExceptionHandlerExceptionResolverWebMvcRegistrationsAdapter`

如果您想完全控制Spring MVC,可以添加自己的@Configuration 注释@EnableWebMvc

HttpMessageConverters

Spring MVC使用该HttpMessageConverter接口来转换HTTP请求和响应。明智的默认设置包含在开箱即用中。例如,对象可以自动转换为JSON(通过使用Jackson库)或XML(如果可用,则使用Jackson XML扩展,或者如果Jackson XML扩展不可用,则使用JAXB)。默认情况下,字符串是以编码的UTF-8

如果需要添加或自定义转换器,可以使用Spring Boot的 HttpMessageConverters类,如下面的清单所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
import org.springframework.boot.autoconfigure.web.HttpMessageConverters;
import org.springframework.context.annotation.*;
import org.springframework.http.converter.*;

@Configuration
public class MyConfiguration {
@Bean
public HttpMessageConverters customConverters() {
HttpMessageConverter<?> additional = ...
HttpMessageConverter<?> another = ...
return new HttpMessageConverters(additional, another);
}
}

HttpMessageConverter上下文中存在的任何bean都将添加到转换器列表中。您也可以以相同的方式覆盖默认转换器。

自定义JSON序列化程序和反序列化程序

如果您使用Jackson序列化和反序列化JSON数据,您可能希望编写自己的类JsonSerializerJsonDeserializer类。自定义序列化程序通常 通过模块向Jackson注册,但Spring Boot提供了另一种@JsonComponent注释,可以更容易地直接注册Spring Beans。

您可以@JsonComponent直接使用注释JsonSerializerJsonDeserializer实现。您还可以在包含序列化程序/反序列化程序作为内部类的类上使用它,如以下示例所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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豆子都会ApplicationContext自动在杰克逊注册。因为@JsonComponent是元注释@Component,所以通常的组件扫描规则适用。

春季启动也提供 JsonObjectSerializerJsonObjectDeserializer基础类,序列化对象时提供标准版本的杰克逊有用的替代。见 JsonObjectSerializerJsonObjectDeserializer在Javadoc了解详情。

MessageCodesResolver

Spring MVC有一个生成错误代码的策略,用于从绑定错误中呈现错误消息:MessageCodesResolver。如果设置了spring.mvc.message-codes-resolver.format财产PREFIX_ERROR_CODEPOSTFIX_ERROR_CODE春季启动为您创建一个(见枚举DefaultMessageCodesResolver.Format)。

静态内容

默认情况下,Spring Boot从类路径中的/static/public/resources/META-INF/resources)目录或者根目录中提供静态内容ServletContext。它使用ResourceHttpRequestHandlerSpring MVC,以便您可以通过添加自己WebMvcConfigureraddResourceHandlers方法来修改该行为并覆盖该 方法。

在独立的Web应用程序中,容器中的默认servlet也会启用,并作为后备,从ServletContextif 的根目录提供内容,决定不处理它。大多数情况下,这不会发生(除非你修改默认的MVC配置),因为Spring总是可以通过它来处理请求 DispatcherServlet

默认情况下,会映射资源/**,但您可以使用该spring.mvc.static-path-pattern属性对其进行调整 。例如,重新定位所有资源 /resources/**可以实现如下:

1
spring.mvc.static-path-pattern = /resources/**

您还可以使用该spring.resources.static-locations属性自定义静态资源位置 (将默认值替换为目录位置列表)。根Servlet上下文路径"/"也会自动添加为位置。

除了前面提到的“标准”静态资源位置之外,还为Webjars内容制作了一个特例。具有路径的任何资源 /webjars/**都是从jar文件提供的,如果它们以Webjars格式打包的话。

src/main/webapp如果您的应用程序打包为jar,请不要使用该目录。虽然这个目录是一个通用的标准,它的工作原理只是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.zWebjar版本在哪里。

如果你使用JBoss,你需要声明webjars-locator-jboss-vfs 依赖而不是webjars-locator-core。否则,所有Webjars都会解析为 404

要使用缓存清除,以下配置会为所有静态资源配置缓存清除解决方案,从而有效地<link href="/css/spring-2a2d595e6ed9a0b24f027f2b63b134d6.css"/>在URL中添加内容哈希,例如 :

1
2
spring.resources.chain.strategy.content.enabled = true
spring.resources.chain.strategy.content.paths = /**

由于ResourceUrlEncodingFilter为Thymeleaf和FreeMarker自动配置了资源链接,因此在运行时会在模板中重写 。您应该在使用JSP时手动声明此过滤器。目前不支持其他模板引擎,但可以使用自定义模板宏/帮助程序和使用 ResourceUrlProvider

使用(例如)JavaScript模块加载器动态加载资源时,不能重命名文件。这就是为什么其他策略也得到支持并可以合并的原因。“固定”策略在URL中添加静态版本字符串而不更改文件名,如以下示例所示:

1
2
3
4
5
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"),而其他资源仍使用内容one(<link href="/css/spring-2a2d595e6ed9a0b24f027f2b63b134d6.css"/>)。

有关更多支持选项,请参阅ResourceProperties

此功能已在专门的博客文章和Spring Framework的 参考文档中进行了详细描述 。

欢迎页面

Spring Boot支持静态和模板化欢迎页面。它首先index.html在配置的静态内容位置中查找 文件。如果找不到,则查找index模板。如果找到任何一个,它将自动用作应用程序的欢迎页面。

自定义Favicon

Spring Boot favicon.ico在配置的静态内容位置和类路径的根(按此顺序)中查找a 。如果存在这样的文件,它将自动用作应用程序的favicon。

路径匹配和内容协商

Spring MVC可以通过查看请求路径并将其与应用程序中定义的映射(例如,@GetMapping Controller方法上的注释)相匹配,将传入的HTTP请求映射到处理程序。

Spring Boot默认选择禁用后缀模式匹配,这意味着请求"GET /projects/spring-boot.json"不会与@GetMapping("/projects/spring-boot")映射匹配 。这被认为是Spring MVC应用程序最佳实践。对于没有发送正确“接受”请求标头的HTTP客户端,此功能在过去主要有用; 我们需要确保将正确的内容类型发送给客户端。如今,内容协商更加可靠。

还有其他方法可以处理不一致发送正确“接受”请求标头的HTTP客户端。我们可以使用查询参数来确保将请求"GET /projects/spring-boot?format=json" 映射到@GetMapping("/projects/spring-boot")以下内容,而不是使用后缀匹配:

1
2
3
4
5
6
7
spring.mvc.contentnegotiation.favor-parameter = true

#我们可以更改参数名称,默认为“format”:
#spring.mvc.contentnegotiation.parameter-name = myparam

#我们还可以注册其他文件扩展名/媒体类型:
spring.mvc.contentnegotiation.media-types.markdown = text/markdown

如果您了解警告并仍希望您的应用程序使用后缀模式匹配,则需要以下配置:

1
2
spring.mvc.contentnegotiation.favor-path-extension = true
spring.mvc.pathmatch.use-suffix-pattern = true

或者,不是打开所有后缀模式,而是仅支持已注册的后缀模式更安全:

1
2
3
4
5
spring.mvc.contentnegotiation.favor-path-extension = true
spring.mvc.pathmatch.use-registered-suffix-pattern = true

#您还可以注册其他文件扩展名/媒体类型:
#spring.mvc.contentnegotiation.media-types.adoc = text/asciidoc

ConfigurableWebBindingInitializer

Spring MVC使用一个 WebBindingInitializer来初始化WebDataBinder特定请求。如果你自己创建ConfigurableWebBindingInitializer @Bean,Spring Boot会自动配置Spring MVC来使用它。

模板引擎

除REST Web服务外,您还可以使用Spring MVC来提供动态HTML内容。Spring MVC支持各种模板技术,包括Thymeleaf,FreeMarker和JSP。此外,许多其他模板引擎包括他们自己的Spring MVC集成。

Spring Boot包括对以下模板引擎的自动配置支持:

如果可能,应该避免使用JSP。将它们与嵌入式servlet容器一起使用时有几个 已知的限制

当您使用其中一个模板引擎和默认配置时,您的模板将自动从中获取src/main/resources/templates

根据您运行应用程序的方式,IntelliJ IDEA以不同方式对类路径进行排序。从主方法在IDE中运行应用程序会导致与使用Maven或Gradle或其打包的jar运行应用程序时的顺序不同。这可能导致Spring Boot无法在类路径中找到模板。如果遇到此问题,可以在IDE中重新排序类路径,以便首先放置模块的类和资源。或者,您可以配置模板前缀以搜索templates类路径上的每个目录,如下所示: classpath*:/templates/

错误处理

默认情况下,Spring Boot提供了一个/error以合理方式处理所有错误的映射,并将其注册为servlet容器中的“全局”错误页面。对于计算机客户端,它会生成一个JSON响应,其中包含错误,HTTP状态和异常消息的详细信息。对于浏览器客户端,有一个“whitelabel”错误视图,它以HTML格式呈现相同的数据(以自定义它,添加View解析后的数据error)。要完全替换默认行为,您可以实现 ErrorController并注册该类型的bean定义,或者添加类型的bean ErrorAttributes以使用现有机制但替换内容。

BasicErrorController可以用作自定义基类 ErrorController。如果要为新内容类型添加处理程序(默认情况下是text/html专门处理并为其他所有内容提供后备),这将特别有用。为此,请扩展BasicErrorController,添加@RequestMapping具有produces属性的公共方法 ,并创建新类型的bean。

您还可以定义一个带注释的类,@ControllerAdvice以自定义要为特定控制器和/或异常类型返回的JSON文档,如以下示例所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@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);
}
}

在前面的示例中,如果YourException由在同一个包中定义的控制器抛出,则使用POJO AcmeController的JSON表示CustomErrorType而不是ErrorAttributes表示。

自定义错误页面

如果要显示给定状态代码的自定义HTML错误页面,可以将文件添加到文件/error夹。错误页面可以是静态HTML(即,添加到任何静态资源文件夹下),也可以使用模板构建。文件名应该是确切的状态代码或系列掩码。

例如,要映射404到静态HTML文件,您的文件夹结构如下:

1
2
3
4
5
6
7
8
9
src/
+- main/
+- java/
| + <source code>
+- resources/
+- public/
+- error/
| +- 404.html
+- <other public assets>

5xx使用FreeMarker模板映射所有错误,您的文件夹结构如下:

1
2
3
4
5
6
7
8
9
src/
+- main/
+- java/
| + <source code>
+- resources/
+- templates/
+- error/
| +- 5xx.ftl
+- <other templates>

对于更复杂的映射,您还可以添加实现该ErrorViewResolver 接口的bean ,如以下示例所示:

1
2
3
4
5
6
7
8
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

1
2
3
4
5
6
7
8
9
10
11
@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调度程序,如以下示例所示:

1
2
3
4
5
6
7
8
@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使用其错误页面过滤器将具有错误状态的请求转发到相应的错误页面。如果尚未提交响应,则只能将请求转发到正确的错误页面。缺省情况下,WebSphere Application Server 8.0及更高版本在成功完成servlet的服务方法后提交响应。您应该通过设置com.ibm.ws.webcontainer.invokeFlushAfterService为禁用此行为 false

Spring HATEOAS

如果您开发使用超媒体的RESTful API,Spring Boot为Spring HATEOAS提供自动配置,适用于大多数应用程序。自动配置取代了使用@EnableHypermediaSupport和注册多个bean 的需要,以便于构建基于超媒体的应用程序,包括 LinkDiscoverers(用于客户端支持)和ObjectMapper配置为正确编组响应到所需表示的响应。的ObjectMapper是通过设置各种定制的spring.jackson.*属性,或者,如果存在的话,通过一个Jackson2ObjectMapperBuilder豆。

您可以使用控制Spring HATEOAS的配置 @EnableHypermediaSupport。请注意,这样做会禁用ObjectMapper前面描述的自定义。

CORS支持

跨源资源共享 (CORS)是大多数浏览器实现 的W3C规范,允许您以灵活的方式指定授权何种跨域请求,而不是使用一些安全性较低且功能较弱的方法,如IFRAME或JSONP。

从版本4.2开始,Spring MVC 支持CORS。 在Spring Boot应用程序中使用带有 注释的控制器方法CORS配置@CrossOrigin不需要任何特定配置。 可以通过使用自定义方法注册bean 来定义全局CORS配置,如以下示例所示:WebMvcConfigurer. addCorsMappings(CorsRegistry)

1
2
3
4
5
6
7
8
9
10
11
12
@Configuration
public class MyConfiguration {
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/api/**");
}
};
}
}

Spring WebFlux框架

Spring WebFlux是Spring Framework 5.0中引入的新的响应式Web框架。与Spring MVC不同,它不需要Servlet API,完全异步且无阻塞,并 通过Reactor项目实现Reactive Streams规范。

Spring WebFlux有两种版本:基于功能和注释。基于注释的注释非常接近Spring MVC模型,如以下示例所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@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”是功能变体,它将路由配置与请求的实际处理分开,如以下示例所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
@Configuration
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 Framework的一部分,详细信息可在其 参考文档中找到

您可以根据需要定义任意数量的RouterFunctionbean来模块化路由器的定义。如果需要应用优先级,可以订购Bean。

要开始,请将spring-boot-starter-webflux模块添加到您的应用程序中。

在应用程序中添加两个spring-boot-starter-webspring-boot-starter-webflux模块会导致Spring Boot自动配置Spring MVC,而不是WebFlux。选择此行为是因为许多Spring开发人员spring-boot-starter-webflux 在其Spring MVC应用程序中添加了使用被动的WebClient。您仍然可以通过将所选应用程序类型设置为来强制执行您的选择SpringApplication.setWebApplicationType(WebApplicationType.REACTIVE)

Spring WebFlux自动配置

Spring Boot为Spring WebFlux提供自动配置,适用于大多数应用程序。

自动配置在Spring的默认值之上添加了以下功能:

如果你想保留Spring Boot WebFlux功能,并且想要添加额外的 WebFlux配置,你可以添加自己的 @Configuration类类WebFluxConfigurer不需要@EnableWebFlux

如果您想完全控制Spring WebFlux,可以添加自己的 @Configuration注释@EnableWebFlux

带有HttpMessageReaders和HttpMessageWriters的HTTP编解码器

Spring WebFlux使用HttpMessageReaderHttpMessageWriter接口转换HTTP请求和响应。CodecConfigurer通过查看类路径中可用的库,它们被配置为具有合理的默认值。

Spring Boot通过使用CodecCustomizer实例进一步自定义。例如,spring.jackson.*配置密钥应用于Jackson编解码器。

如果需要添加或自定义编解码器,可以创建自定义CodecCustomizer 组件,如以下示例所示:

1
2
3
4
5
6
7
8
9
10
11
import org.springframework.boot.web.codec.CodecCustomizer;

@Configuration
public class MyConfiguration {
@Bean
public CodecCustomizer myCodecCustomizer() {
return codecConfigurer -> {
// ...
}
}
}

您还可以利用Boot的自定义JSON序列化程序和反序列化程序

静态内容

默认情况下,Spring Boot从类路径中名为/static/public/resources/META-INF/resources)的目录中提供静态内容。它使用ResourceWebHandlerSpring WebFlux,以便您可以通过添加自己WebFluxConfigureraddResourceHandlers方法来修改该行为并覆盖该方法。

默认情况下,映射资源/**,但您可以通过设置spring.webflux.static-path-pattern属性来调整它 。例如,重新定位所有资源 /resources/**可以实现如下:

1
spring.webflux.static-path-pattern = /resources/**

您还可以使用自定义静态资源位置 spring.resources.static-locations。这样做会将默认值替换为目录位置列表。如果这样做,默认的欢迎页面检测将切换到您的自定义位置。因此,如果index.html您的任何位置在启动时存在,则它是应用程序的主页。

除了前面列出的“标准”静态资源位置之外,还为Webjars内容制作了一个特例。具有路径的任何资源 /webjars/**都是从jar文件提供的,如果它们以Webjars格式打包的话。

Spring WebFlux应用程序并不严格依赖于Servlet API,因此它们不能作为war文件部署,也不能使用该src/main/webapp目录。

模板引擎

除REST Web服务外,您还可以使用Spring WebFlux来提供动态HTML内容。Spring WebFlux支持各种模板技术,包括Thymeleaf,FreeMarker和Mustache。

Spring Boot包括对以下模板引擎的自动配置支持:

当您使用其中一个模板引擎和默认配置时,您的模板将自动从中获取src/main/resources/templates

错误处理

Spring Boot提供了WebExceptionHandler一种以合理的方式处理所有错误的方法。它在处理顺序中的位置紧接在WebFlux提供的处理程序之前,这些处理程序被认为是最后一个。对于计算机客户端,它会生成一个JSON响应,其中包含错误,HTTP状态和异常消息的详细信息。对于浏览器客户端,有一个“whitelabel”错误处理程序,它以HTML格式呈现相同的数据。您还可以提供自己的HTML模板来显示错误(请参阅 下一节)。

自定义此功能的第一步通常涉及使用现有机制,但替换或扩充错误内容。为此,您可以添加类型的bean ErrorAttributes

要更改错误处理行为,可以实现ErrorWebExceptionHandler并注册该类型的bean定义。由于a WebExceptionHandler是一个非常低级的,Spring Boot还提供了一个方便AbstractErrorWebExceptionHandler的让你以WebFlux功能方式处理错误,如下例所示:

1
2
3
4
5
6
7
8
9
10
public class CustomErrorWebExceptionHandler extends AbstractErrorWebExceptionHandler {
//在这里定义构造函数
@Override
protected RouterFunction<ServerResponse> getRoutingFunction(ErrorAttributes errorAttributes) {

return RouterFunctions
.route(aPredicate, aHandler)
.andRoute(anotherPredicate, anotherHandler);
}
}

要获得更完整的图片,您还可以DefaultErrorWebExceptionHandler 直接子类化并覆盖特定方法。

自定义错误页面

如果要显示给定状态代码的自定义HTML错误页面,可以将文件添加到文件/error夹。错误页面可以是静态HTML(即,添加到任何静态资源文件夹下)或使用模板构建。文件名应该是确切的状态代码或系列掩码。

例如,要映射404到静态HTML文件,您的文件夹结构如下:

1
2
3
4
5
6
7
8
9
src/
+- main/
+- java/
| + <source code>
+- resources/
+- public/
+- error/
| +- 404.html
+- <other public assets>

5xx使用Mustache模板映射所有错误,您的文件夹结构如下:

1
2
3
4
5
6
7
8
9
src/
+- main/
+- java/
| + <source code>
+- resources/
+- templates/
+- error/
| +- 5xx.mustache
+- <other templates>

Web过滤器

Spring WebFlux提供了一个WebFilter可以实现过滤HTTP请求 - 响应交换的接口。WebFilter在应用程序上下文中找到的bean将自动用于过滤每个交换。

如果过滤器的顺序很重要,则可以实现Ordered或注释@Order。Spring Boot自动配置可以为您配置Web过滤器。执行此操作时,将使用下表中显示的订单:

Web Filter Order
MetricsWebFilter Ordered.HIGHEST_PRECEDENCE + 1
WebFilterChainProxy (spring Security) -100
HttpTraceWebFilter Ordered.LOWEST_PRECEDENCE - 10

JAX-RS and Jersey

如果您更喜欢REST端点的JAX-RS编程模型,则可以使用其中一个可用的实现而不是Spring MVC。JerseyApache CXF开箱即用。CXF要求您在应用程序上下文中注册ServletFilter作为其注册@Bean。Jersey有一些原生的Spring支持,因此我们还在Spring Boot中为它提供了自动配置支持以及启动器。

要开始使用Jersey,请将其spring-boot-starter-jersey作为依赖项包含在内,然后您需要一个注册所有端点@Bean的类型ResourceConfig,如以下示例所示:

1
2
3
4
5
6
@Component
public class JerseyConfig extends ResourceConfig {
public JerseyConfig() {
register(Endpoint.class);
}
}

Jersey对扫描可执行档案的支持相当有限。例如,它无法扫描完全可执行jar文件中的包中或WEB-INF/classes运行可执行war文件时的端点。为避免此限制,packages不应使用该方法,并且应使用该register方法单独注册端点,如上例所示。

对于更高级的自定义,您还可以注册实现的任意数量的bean ResourceConfigCustomizer

所有已注册的端点都应@Components使用HTTP资源注释(@GET和其他),如以下示例所示:

1
2
3
4
5
6
7
8
@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.*

有一个Jersey sample以便您可以看到如何设置。

嵌入式Servlet容器支持

Spring Boot包括对嵌入式TomcatJettyUndertow服务器的支持。大多数开发人员使用适当的“Starter”来获取完全配置的实例。默认情况下,嵌入式服务器侦听端口上的HTTP请求8080

如果您选择在CentOS上使用Tomcat ,请注意,默认情况下,临时目录用于存储已编译的JSP,文件上载等。tmpwatch应用程序运行时可能会删除此目录,从而导致失败。要避免此行为,您可能希望自定义tmpwatch配置,以便tomcat.*不删除或配置目录以server.tomcat.basedir使嵌入式Tomcat使用其他位置。

Servlet,Filter和Listeners

使用嵌入式servlet容器时,可以HttpSessionListener通过使用Spring bean或扫描Servlet组件,从Servlet规范中注册servlet,过滤器和所有侦听器(如HttpSessionListener)。

将Servlet,过滤器和监听器注册为Spring Bean

作为Spring bean的任何ServletFilter或者servlet *Listener实例都是在嵌入式容器中注册的。如果要从application.properties配置期间引用值,这可能特别方便。

默认情况下,如果上下文仅包含一个Servlet,则将其映射到/。在多个servlet bean的情况下,bean名称用作路径前缀。过滤器映射到 /*

如果以公约为基础测绘不够灵活,你可以使用 ServletRegistrationBeanFilterRegistrationBean以及 ServletListenerRegistrationBean类的完全控制。

Spring Boot附带了许多可以定义Filter bean的自动配置。以下是过滤器及其各自顺序的一些示例(较低的顺序值表示较高的优先级):

ServletFilter Order
OrderedCharacterEncodingFilter Ordered.HIGHEST_PRECEDENCE
WebMvcMetricsFilter Ordered.HIGHEST_PRECEDENCE + 1
ErrorPageFilter Ordered.HIGHEST_PRECEDENCE + 1
HttpTraceFilter Ordered.LOWEST_PRECEDENCE - 10

将Filter beans无序放置通常是安全的。

如果需要特定的顺序,则应避免配置读取请求主体的过滤器Ordered.HIGHEST_PRECEDENCE,因为它可能违反应用程序的字符编码配置。如果Servlet过滤器包装请求,则应使用小于或等于的顺序进行配置 OrderedFilter.REQUEST_WRAPPER_FILTER_MAX_ORDER

Servlet上下文初始化

嵌入式servlet容器不直接执行Servlet 3.0+ javax.servlet.ServletContainerInitializer接口或Springorg.springframework.web.WebApplicationInitializer接口。这是一个有意的设计决策,旨在降低设计在战争中运行的第三方库可能会破坏Spring Boot应用程序的风险。

如果需要在Spring Boot应用程序中执行servlet上下文初始化,则应注册实现该org.springframework.boot.web.servlet.ServletContextInitializer接口的bean 。单一onStartup方法提供对s的访问,ServletContext并且如果需要,可以轻松地用作现有的适配器WebApplicationInitializer

扫描Servlet,过滤器和侦听器

当使用嵌入式容器中,类自动登记注释有 @WebServlet@WebFilter@WebListener可以通过使用被使能 @ServletComponentScan

@ServletComponentScan 在独立容器中没有任何效果,而是使用容器的内置发现机制。

ServletWebServerApplicationContext

在引擎盖下,Spring Boot使用不同类型的ApplicationContext嵌入式servlet容器支持。该ServletWebServerApplicationContext是一种特殊类型的WebApplicationContext通过搜索单说引导自身 ServletWebServerFactory豆。通常是TomcatServletWebServerFactory,,JettyServletWebServerFactoryUndertowServletWebServerFactory 已经自动配置。

您通常不需要了解这些实现类。大多数应用程序都自动配置,并适当的ApplicationContextServletWebServerFactory以您的名义创建。

自定义嵌入式Servlet容器

可以使用Spring Environment 属性配置公共servlet容器设置。通常,您将在application.properties 文件中定义属性。

常用服务器设置包括:

  • 网络设置:侦听传入HTTP请求的端口(server.port),要绑定的接口地址server.address等等。
  • 会话设置:会话是持久性(server.servlet.session.persistence),会话超时(server.servlet.session.timeout),会话数据(server.servlet.session.store-dir)的位置以及会话cookie配置(server.servlet.session.cookie.*)。
  • 错误管理:错误页面的位置(server.error.path)等。
  • SSL
  • HTTP compression

Spring Boot尽可能尝试公开常见设置,但这并不总是可行。对于这些情况,专用命名空间提供特定于服务器的自定义(请参阅 server.tomcatserver.undertow)。例如, 可以使用嵌入式servlet容器的特定功能配置访问日志

请参阅 ServerProperties课程以获取完整列表。

程序化定制

如果需要以编程方式配置嵌入式servlet容器,可以注册实现该WebServerFactoryCustomizer接口的Spring bean 。 WebServerFactoryCustomizer提供对其的访问 ConfigurableServletWebServerFactory,其中包括许多自定义setter方法。以下示例以编程方式设置端口:

1
2
3
4
5
6
7
8
9
10
11
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);
}
}

TomcatServletWebServerFactoryJettyServletWebServerFactory并且UndertowServletWebServerFactory 是专用变体,ConfigurableServletWebServerFactory分别为Tomcat,Jetty和Undertow提供了额外的自定义setter方法。

直接自定义ConfigurableServletWebServerFactory

如果前面的定制技术太有限,你可以注册 TomcatServletWebServerFactoryJettyServletWebServerFactoryUndertowServletWebServerFactory bean。

1
2
3
4
5
6
7
8
@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;
}

为许多配置选项提供了Setter。如果您需要做一些更具异国情调的事情,还会提供一些受保护的方法“挂钩”。有关详细信息,请参阅 源代码文档

JSP限制

运行使用嵌入式servlet容器的Spring Boot应用程序(并打包为可执行存档)时,JSP支持存在一些限制。

  • 使用Jetty和Tomcat,如果使用war包装,它应该可以工作。可执行的war将在启动时运行java -jar,并且也可以部署到任何标准容器。使用可执行jar时不支持JSP。
  • Undertow不支持JSP。
  • 创建自定义error.jsp页面不会覆盖错误处理的默认视图 。 应该使用自定义错误页面

有一个JSP示例以便您可以看到如何设置。

嵌入式Reactive Server支持

Spring Boot包括对以下嵌入式响应式Web服务器的支持:Reactor Netty,Tomcat,Jetty和Undertow。大多数开发人员使用适当的“Starter”来获取完全配置的实例。默认情况下,嵌入式服务器在端口8080上侦听HTTP请求。

Reactive Server资源配置

在自动配置Reactor Netty或Jetty服务器时,Spring Boot将创建特定的bean,为服务器实例提供HTTP资源:ReactorResourceFactoryJettyResourceFactory

默认情况下,这些资源也将与Reactor Netty和Jetty客户端共享,以获得最佳性能,具体如下:

  • 相同的技术用于服务器和客户端
  • 客户端实例是使用WebClient.BuilderSpring Boot自动配置的bean 构建的

开发人员可以通过提供自定义ReactorResourceFactoryJettyResourceFactorybean 来覆盖Jetty和Reactor Netty的资源配置- 这将应用于客户端和服务器。

您可以在WebClient Runtime部分中了解有关客户端资源配置的更多信息 。