Reactive Web Applications

Spring Boot 通过为 Spring Webflux 提供自动配置来简化响应式 Web 应用程序的开发。

Spring Boot simplifies development of reactive web applications by providing auto-configuration for Spring Webflux.

The “Spring WebFlux Framework”

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

Spring WebFlux is the new reactive web framework introduced in Spring Framework 5.0. Unlike Spring MVC, it does not require the servlet API, is fully asynchronous and non-blocking, and implements the Reactive Streams specification through the Reactor project.

Spring WebFlux 有两种模式:基于函数和基于注解。基于注解的模式非常接近 Spring MVC 模型,如下例所示:

Spring WebFlux comes in two flavors: functional and annotation-based. The annotation-based one is quite close to the Spring MVC model, as shown in the following example:

WebFlux 是 Spring Framework 的一部分,其详细信息可在 {url-spring-framework-docs}/web/webflux.html[参考文档] 中找到。

WebFlux is part of the Spring Framework and detailed information is available in its {url-spring-framework-docs}/web/webflux.html[reference documentation].

“WebFlux.fn”,函数变体将路由配置与请求的实际处理分离开来,如下例所示:

“WebFlux.fn”, the functional variant, separates the routing configuration from the actual handling of the requests, as shown in the following example:

"`WebFlux.fn`"是 Spring Framework 的一部分,其详细信息可在 {url-spring-framework-docs}/web/webflux-functional.html[参考文档] 中找到。

“WebFlux.fn” is part of the Spring Framework and detailed information is available in its {url-spring-framework-docs}/web/webflux-functional.html[reference documentation].

你可以根据需要定义任意数量的 `RouterFunction`bean 来模块化路由器的定义。如果需要应用优先级,可以对 bean 进行排序。

You can define as many RouterFunction beans as you like to modularize the definition of the router. Beans can be ordered if you need to apply a precedence.

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

To get started, add the spring-boot-starter-webflux module to your application.

在应用程序中同时添加 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)`来强制执行您的选择。

Adding both spring-boot-starter-web and spring-boot-starter-webflux modules in your application results in Spring Boot auto-configuring Spring MVC, not WebFlux. This behavior has been chosen because many Spring developers add spring-boot-starter-webflux to their Spring MVC application to use the reactive WebClient. You can still enforce your choice by setting the chosen application type to SpringApplication.setWebApplicationType(WebApplicationType.REACTIVE).

Spring WebFlux Auto-configuration

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

Spring Boot provides auto-configuration for Spring WebFlux that works well with most applications.

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

The auto-configuration adds the following features on top of Spring’s defaults:

如果您想保留 Spring Boot WebFlux 功能并且想添加其他 {url-spring-framework-docs}/web/webflux/config.html[WebFlux 配置],您可以添加自己的 @Configuration`类,类型为 `WebFluxConfigurer`但 without `@EnableWebFlux

If you want to keep Spring Boot WebFlux features and you want to add additional {url-spring-framework-docs}/web/webflux/config.html[WebFlux configuration], you can add your own @Configuration class of type WebFluxConfigurer but without @EnableWebFlux.

如果您想对自动配置的 HttpHandler`进行其他自定义,可以定义 `WebHttpHandlerBuilderCustomizer`类型的 bean 并使用它们修改 `WebHttpHandlerBuilder

If you want to add additional customization to the auto-configured HttpHandler, you can define beans of type WebHttpHandlerBuilderCustomizer and use them to modify the WebHttpHandlerBuilder.

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

If you want to take complete control of Spring WebFlux, you can add your own @Configuration annotated with @EnableWebFlux.

Spring WebFlux Conversion Service

如果你要自定义 Spring WebFlux 用到的 ConversionService,你可以提供一个带有 addFormatters 方法的 WebFluxConfigurer Bean。

If you want to customize the ConversionService used by Spring WebFlux, you can provide a WebFluxConfigurer bean with an addFormatters method.

转换也可以使用 spring.webflux.format.* 配置属性来自定义。如果没有配置,则将使用以下默认值:

Conversion can also be customized using the spring.webflux.format.* configuration properties. When not configured, the following defaults are used:

Property DateTimeFormatter

configprop:spring.webflux.format.date[]

ofLocalizedDate(FormatStyle.SHORT)

configprop:spring.webflux.format.time[]

ofLocalizedTime(FormatStyle.SHORT)

configprop:spring.webflux.format.date-time[]

ofLocalizedDateTime(FormatStyle.SHORT)

HTTP Codecs with HttpMessageReaders and HttpMessageWriters

Spring WebFlux 使用 HttpMessageReaderHttpMessageWriter 接口来转换 HTTP 请求和响应。它们使用 CodecConfigurer 进行配置来查看类路径中可用的库,以获得合理的默认值。

Spring WebFlux uses the HttpMessageReader and HttpMessageWriter interfaces to convert HTTP requests and responses. They are configured with CodecConfigurer to have sensible defaults by looking at the libraries available in your classpath.

Spring Boot 为编解码器提供了专用的配置属性,spring.codec.. It also applies further customization by using CodecCustomizer instances. For example, spring.jackson. 配置键应用到 Jackson 编解码器。

Spring Boot provides dedicated configuration properties for codecs, spring.codec.. It also applies further customization by using CodecCustomizer instances. For example, spring.jackson. configuration keys are applied to the Jackson codec.

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

If you need to add or customize codecs, you can create a custom CodecCustomizer component, as shown in the following example:

Static Content

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

By default, Spring Boot serves static content from a directory called /static (or /public or /resources or /META-INF/resources) in the classpath. It uses the ResourceWebHandler from Spring WebFlux so that you can modify that behavior by adding your own WebFluxConfigurer and overriding the addResourceHandlers method.

默认情况下,资源映射到 /, but you can tune that by setting the configprop:spring.webflux.static-path-pattern[] property. For instance, relocating all resources to /resources/ 上,可按以下方式实现:

By default, resources are mapped on /, but you can tune that by setting the configprop:spring.webflux.static-path-pattern[] property. For instance, relocating all resources to /resources/ can be achieved as follows:

spring:
  webflux:
    static-path-pattern: "/resources/**"

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

You can also customize the static resource locations by using spring.web.resources.static-locations. Doing so replaces the default values with a list of directory locations. If you do so, the default welcome page detection switches to your custom locations. So, if there is an index.html in any of your locations on startup, it is the home page of the application.

除了前面列出的 “standard” 静态资源位置之外,还为 Webjars content 做了一个特例。默认情况下,如果资源的路径在 /webjars/** 中,则会从 jar 文件中提供这些资源(如果它们以 Webjars 格式打包)。可以用 configprop:spring.webflux.webjars-path-pattern[] 属性自定义路径。

In addition to the “standard” static resource locations listed earlier, a special case is made for Webjars content. By default, any resources with a path in /webjars/** are served from jar files if they are packaged in the Webjars format. The path can be customized with the configprop:spring.webflux.webjars-path-pattern[] property.

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

Spring WebFlux applications do not strictly depend on the servlet API, so they cannot be deployed as war files and do not use the src/main/webapp directory.

Welcome Page

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

Spring Boot supports both static and templated welcome pages. It first looks for an index.html file in the configured static content locations. If one is not found, it then looks for an index template. If either is found, it is automatically used as the welcome page of the application.

这只是一个适用于应用程序定义的实际索引路由的回退。排序是由 HandlerMapping bean 的顺序定义的,默认情况下如下:

This only acts as a fallback for actual index routes defined by the application. The ordering is defined by the order of HandlerMapping beans which is by default the following:

RouterFunctionMapping

Endpoints declared with RouterFunction beans

RequestMappingHandlerMapping

Endpoints declared in @Controller beans

RouterFunctionMapping for the Welcome Page

The welcome page support

Template Engines

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

As well as REST web services, you can also use Spring WebFlux to serve dynamic HTML content. Spring WebFlux supports a variety of templating technologies, including Thymeleaf, FreeMarker, and Mustache.

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

Spring Boot includes auto-configuration support for the following templating engines:

当使用默认配置将其中一个模板引擎与之一起使用时,会从 src/main/resources/templates 中自动获取模板。

When you use one of these templating engines with the default configuration, your templates are picked up automatically from src/main/resources/templates.

Error Handling

Spring Boot 提供了一个 WebExceptionHandler ,它以一种明智的方式处理所有错误。在处理顺序中的位置紧靠在 WebFlux 提供的处理程序之前,而后者被考虑为最后。对于机器客户端,它生成一个 JSON 响应,其中包含错误的详细信息、HTTP 状态和异常消息。对于浏览器客户端,有一个 “whitelabel” 错误处理程序,它以 HTML 格式呈现相同的数据。你还可以提供自己的 HTML 模板来显示错误(参见 next section)。

Spring Boot provides a WebExceptionHandler that handles all errors in a sensible way. Its position in the processing order is immediately before the handlers provided by WebFlux, which are considered last. For machine clients, it produces a JSON response with details of the error, the HTTP status, and the exception message. For browser clients, there is a “whitelabel” error handler that renders the same data in HTML format. You can also provide your own HTML templates to display errors (see the next section).

在直接自定义 Spring Boot 中的错误处理之前,你可以利用 Spring WebFlux 中的 {url-spring-framework-docs}/web/webflux/ann-rest-exceptions.html[RFC 7807 Problem Details] 支持。Spring WebFlux 可以生成带有 application/problem+json 媒体类型的自定义错误消息,如下所示:

Before customizing error handling in Spring Boot directly, you can leverage the {url-spring-framework-docs}/web/webflux/ann-rest-exceptions.html[RFC 7807 Problem Details] support in Spring WebFlux. Spring WebFlux can produce custom error messages with the application/problem+json media type, like:

{
	"type": "https://example.org/problems/unknown-project",
	"title": "Unknown project",
	"status": 404,
	"detail": "No project found for id 'spring-unknown'",
	"instance": "/projects/spring-unknown"
}

可以通过将 configprop:spring.webflux.problemdetails.enabled[] 设置为 true 来启用此支持。

This support can be enabled by setting configprop:spring.webflux.problemdetails.enabled[] to true.

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

The first step to customizing this feature often involves using the existing mechanism but replacing or augmenting the error contents. For that, you can add a bean of type ErrorAttributes.

要更改错误处理行为,你可以实现 ErrorWebExceptionHandler 并注册该类型的 Bean 定义。因为 ErrorWebExceptionHandler 相当低级,所以 Spring Boot 还提供了一个方便的 AbstractErrorWebExceptionHandler ,让你以一种 WebFlux 函数式的方式来处理错误,如下例所示:

To change the error handling behavior, you can implement ErrorWebExceptionHandler and register a bean definition of that type. Because an ErrorWebExceptionHandler is quite low-level, Spring Boot also provides a convenient AbstractErrorWebExceptionHandler to let you handle errors in a WebFlux functional way, as shown in the following example:

为了更全面地了解,你还可以直接子类化 DefaultErrorWebExceptionHandler 并覆盖特定的方法。

For a more complete picture, you can also subclass DefaultErrorWebExceptionHandler directly and override specific methods.

在某些情况下,控制器级别的错误不会被 web 观测或 metrics infrastructure 记录。应用程序可以通过 {url-spring-framework-docs}/integration/observability.html#observability.http-server.reactive[在观测上下文中设置已处理异常],来确保这些异常被记录到观测中。

In some cases, errors handled at the controller level are not recorded by web observations or the metrics infrastructure. Applications can ensure that such exceptions are recorded with the observations by {url-spring-framework-docs}/integration/observability.html#observability.http-server.reactive[setting the handled exception on the observation context].

Custom Error Pages

如果你想为给定的状态码显示自定义 HTML 错误页面,你可以添加从 error/* 解析的视图,例如通过将文件添加到 /error 目录。错误页面可以是静态 HTML(即,添加到任何静态资源目录下),也可以使用模板构建。文件名称应该是确切的状态码、状态码系列掩码,或者如果其他都不匹配,则为 error 的默认值。请注意,默认错误视图的路径为 error/error,而使用 Spring MVC 时,默认错误视图为 error

If you want to display a custom HTML error page for a given status code, you can add views that resolve from error/*, for example by adding files to a /error directory. Error pages can either be static HTML (that is, added under any of the static resource directories) or built with templates. The name of the file should be the exact status code, a status code series mask, or error for a default if nothing else matches. Note that the path to the default error view is error/error, whereas with Spring MVC the default error view is error.

例如,要将 404 映射到静态 HTML 文件,你的目录结构如下:

For example, to map 404 to a static HTML file, your directory structure would be as follows:

src/
 +- main/
     +- java/
     |   + <source code>
     +- resources/
         +- public/
             +- error/
             |   +- 404.html
             +- <other public assets>

如果您想使用 Mustache 模板来映射所有 5xx 错误,那么您的目录结构应如下所示:

To map all 5xx errors by using a Mustache template, your directory structure would be as follows:

src/
 +- main/
     +- java/
     |   + <source code>
     +- resources/
         +- templates/
             +- error/
             |   +- 5xx.mustache
             +- <other templates>

Web Filters

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

Spring WebFlux provides a WebFilter interface that can be implemented to filter HTTP request-response exchanges. WebFilter beans found in the application context will be automatically used to filter each exchange.

如果过滤器的顺序很重要,它们可以实现 Ordered 或使用 @Order 进行标注。Spring Boot 自动配置可以为您配置 Web 过滤器。当它这么做时,将会使用下表中所示的顺序:

Where the order of the filters is important they can implement Ordered or be annotated with @Order. Spring Boot auto-configuration may configure web filters for you. When it does so, the orders shown in the following table will be used:

Web Filter Order

WebFilterChainProxy (Spring Security)

-100

HttpExchangesWebFilter

Ordered.LOWEST_PRECEDENCE - 10

Embedded Reactive Server Support

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

Spring Boot includes support for the following embedded reactive web servers: Reactor Netty, Tomcat, Jetty, and Undertow. Most developers use the appropriate “Starter” to obtain a fully configured instance. By default, the embedded server listens for HTTP requests on port 8080.

Customizing Reactive Servers

可以通过 Spring Environment 属性来配置常见的响应式 Web 服务器设置。通常,您会在 application.propertiesapplication.yaml 文件中定义这些属性。

Common reactive web server settings can be configured by using Spring Environment properties. Usually, you would define the properties in your application.properties or application.yaml file.

常见的服务器设置包括:

Common server settings include:

  • Network settings: Listen port for incoming HTTP requests (server.port), interface address to bind to (server.address), and so on.

  • Error management: Location of the error page (server.error.path) and so on.

  • SSL

  • HTTP compression

Spring Boot 尽可能尝试公开常见的设置,但并非总是如此。对于这些情况,诸如 server.netty.* 之类的专用命名空间提供了针对服务器的特定自定义。

Spring Boot tries as much as possible to expose common settings, but this is not always possible. For those cases, dedicated namespaces such as server.netty.* offer server-specific customizations.

请参阅 {code-spring-boot-autoconfigure-src}/web/ServerProperties.java[ServerProperties] 类以获取完整列表。

See the {code-spring-boot-autoconfigure-src}/web/ServerProperties.java[ServerProperties] class for a complete list.

Programmatic Customization

如果您需要以编程方式配置响应式 Web 服务器,则可以注册一个实现了 WebServerFactoryCustomizer 接口的 Spring Bean。WebServerFactoryCustomizer 提供对 ConfigurableReactiveWebServerFactory 的访问权限,其中包括许多自定义 setter 方法。以下示例来说明如何以编程方式设置端口:

If you need to programmatically configure your reactive web server, you can register a Spring bean that implements the WebServerFactoryCustomizer interface. WebServerFactoryCustomizer provides access to the ConfigurableReactiveWebServerFactory, which includes numerous customization setter methods. The following example shows programmatically setting the port:

JettyReactiveWebServerFactoryNettyReactiveWebServerFactoryTomcatReactiveWebServerFactoryUndertowReactiveWebServerFactoryConfigurableReactiveWebServerFactory 的专用变体,分别具有面向 Jetty、Reactor Netty、Tomcat 和 Undertow 的其他自定义 setter 方法。以下示例说明了如何自定义 NettyReactiveWebServerFactory,它提供了对特定于 Reactor Netty 的配置选项的访问权限:

JettyReactiveWebServerFactory, NettyReactiveWebServerFactory, TomcatReactiveWebServerFactory, and UndertowReactiveWebServerFactory are dedicated variants of ConfigurableReactiveWebServerFactory that have additional customization setter methods for Jetty, Reactor Netty, Tomcat, and Undertow respectively. The following example shows how to customize NettyReactiveWebServerFactory that provides access to Reactor Netty-specific configuration options:

Customizing ConfigurableReactiveWebServerFactory Directly

对于从 ReactiveWebServerFactory 扩展所需的更高级用例,您可以自己公开此类类型的 Bean。

For more advanced use cases that require you to extend from ReactiveWebServerFactory, you can expose a bean of such type yourself.

为许多配置选项提供了 Setter。如果您需要执行更奇特的操作,还提供了几个受保护的方法 “hooks”。有关详细信息,请参阅 source code documentation

Setters are provided for many configuration options. Several protected method “hooks” are also provided should you need to do something more exotic. See the source code documentation for details.

自动配置的定制器仍应用于你的自定义工厂,因此请小心使用该选项。

Auto-configured customizers are still applied on your custom factory, so use that option carefully.

Reactive Server Resources Configuration

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

When auto-configuring a Reactor Netty or Jetty server, Spring Boot will create specific beans that will provide HTTP resources to the server instance: ReactorResourceFactory or JettyResourceFactory.

默认情况下,还会将这些资源与 Reactor Netty 和 Jetty 客户端共享以获得最佳性能,因为:

By default, those resources will be also shared with the Reactor Netty and Jetty clients for optimal performances, given:

  • the same technology is used for server and client

  • the client instance is built using the WebClient.Builder bean auto-configured by Spring Boot

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

Developers can override the resource configuration for Jetty and Reactor Netty by providing a custom ReactorResourceFactory or JettyResourceFactory bean - this will be applied to both clients and servers.

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

You can learn more about the resource configuration on the client side in the WebClient Runtime section.