此版本仍在开发中,尚未被视为稳定版本。对于最新的稳定版本,请使用 Spring Boot 3.4.0spring-doc.cn

反应式 Web 应用程序

Spring Boot 通过为 Spring Webflux 提供自动配置来简化反应式 Web 应用程序的开发。spring-doc.cn

“Spring WebFlux 框架”

Spring WebFlux 是 Spring Framework 5.0 中引入的新反应式 Web 框架。 与 Spring MVC 不同,它不需要 servlet API,是完全异步和非阻塞的,并通过 Reactor 项目实现反应流规范。spring-doc.cn

Spring WebFlux 有两种风格:函数式和基于 Comments 的。 基于 Comments 的模型与 Spring MVC 模型非常接近,如以下示例所示:spring-doc.cn

import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

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 Mono<User> getUser(@PathVariable Long userId) {
		return this.userRepository.findById(userId);
	}

	@GetMapping("/{userId}/customers")
	public Flux<Customer> getUserCustomers(@PathVariable Long userId) {
		return this.userRepository.findById(userId).flatMapMany(this.customerRepository::findByUser);
	}

	@DeleteMapping("/{userId}")
	public Mono<Void> deleteUser(@PathVariable Long userId) {
		return this.userRepository.deleteById(userId);
	}

}
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
import reactor.core.publisher.Flux
import reactor.core.publisher.Mono

@RestController
@RequestMapping("/users")
class MyRestController(private val userRepository: UserRepository, private val customerRepository: CustomerRepository) {

	@GetMapping("/{userId}")
	fun getUser(@PathVariable userId: Long): Mono<User?> {
		return userRepository.findById(userId)
	}

	@GetMapping("/{userId}/customers")
	fun getUserCustomers(@PathVariable userId: Long): Flux<Customer> {
		return userRepository.findById(userId).flatMapMany { user: User? ->
			customerRepository.findByUser(user)
		}
	}

	@DeleteMapping("/{userId}")
	fun deleteUser(@PathVariable userId: Long): Mono<Void> {
		return userRepository.deleteById(userId)
	}

}

WebFlux 是 Spring Framework 的一部分,其参考文档中提供了详细信息。spring-doc.cn

“WebFlux.fn”是功能变体,它将路由配置与请求的实际处理分开,如以下示例所示:spring-doc.cn

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.web.reactive.function.server.RequestPredicate;
import org.springframework.web.reactive.function.server.RouterFunction;
import org.springframework.web.reactive.function.server.ServerResponse;

import static org.springframework.web.reactive.function.server.RequestPredicates.accept;
import static org.springframework.web.reactive.function.server.RouterFunctions.route;

@Configuration(proxyBeanMethods = false)
public class MyRoutingConfiguration {

	private static final RequestPredicate ACCEPT_JSON = accept(MediaType.APPLICATION_JSON);

	@Bean
	public RouterFunction<ServerResponse> monoRouterFunction(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.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.http.MediaType
import org.springframework.web.reactive.function.server.RequestPredicates.DELETE
import org.springframework.web.reactive.function.server.RequestPredicates.GET
import org.springframework.web.reactive.function.server.RequestPredicates.accept
import org.springframework.web.reactive.function.server.RouterFunction
import org.springframework.web.reactive.function.server.RouterFunctions
import org.springframework.web.reactive.function.server.ServerResponse

@Configuration(proxyBeanMethods = false)
class MyRoutingConfiguration {

	@Bean
	fun monoRouterFunction(userHandler: MyUserHandler): RouterFunction<ServerResponse> {
		return RouterFunctions.route(
			GET("/{user}").and(ACCEPT_JSON), userHandler::getUser).andRoute(
			GET("/{user}/customers").and(ACCEPT_JSON), userHandler::getUserCustomers).andRoute(
			DELETE("/{user}").and(ACCEPT_JSON), userHandler::deleteUser)
	}

	companion object {
		private val ACCEPT_JSON = accept(MediaType.APPLICATION_JSON)
	}

}
import reactor.core.publisher.Mono;

import org.springframework.stereotype.Component;
import org.springframework.web.reactive.function.server.ServerRequest;
import org.springframework.web.reactive.function.server.ServerResponse;

@Component
public class MyUserHandler {

	public Mono<ServerResponse> getUser(ServerRequest request) {
		...
	}

	public Mono<ServerResponse> getUserCustomers(ServerRequest request) {
		...
	}

	public Mono<ServerResponse> deleteUser(ServerRequest request) {
		...
	}

}
import org.springframework.stereotype.Component
import org.springframework.web.reactive.function.server.ServerRequest
import org.springframework.web.reactive.function.server.ServerResponse
import reactor.core.publisher.Mono

@Component
class MyUserHandler {

	fun getUser(request: ServerRequest?): Mono<ServerResponse> {
		...
	}

	fun getUserCustomers(request: ServerRequest?): Mono<ServerResponse> {
		...
	}

	fun deleteUser(request: ServerRequest?): Mono<ServerResponse> {
		...
	}

}

“WebFlux.fn” 是 Spring Framework 的一部分,详细信息可在其参考文档中找到。spring-doc.cn

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

要开始使用,请将模块添加到您的应用程序中。spring-boot-starter-webfluxspring-doc.cn

在应用程序中添加 and 模块会导致 Spring Boot 自动配置 Spring MVC,而不是 WebFlux。 之所以选择这种行为,是因为许多 Spring 开发人员添加到他们的 Spring MVC 应用程序中以使用反应式WebClient。 您仍然可以通过将所选应用程序类型设置为 来强制执行您的选择。spring-boot-starter-webspring-boot-starter-webfluxspring-boot-starter-webfluxSpringApplication.setWebApplicationType(WebApplicationType.REACTIVE)

Spring WebFlux 自动配置

Spring Boot 为 Spring WebFlux 提供了自动配置,适用于大多数应用程序。spring-doc.cn

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

如果要保留 Spring Boot WebFlux 功能,并且想要添加其他 WebFlux 配置,则可以添加自己的WebFluxConfigurer类型的@Configuration类,但不添加@EnableWebFluxspring-doc.cn

如果要向自动配置的HttpHandler添加其他自定义,则可以定义WebHttpHandlerBuilderCustomizer类型的 bean 并使用它们来修改WebHttpHandlerBuilderspring-doc.cn

如果您想完全控制 Spring WebFlux,您可以添加自己的 @Configuration 并带有 @EnableWebFlux 注解。spring-doc.cn

Spring WebFlux 转换服务

如果要自定义 Spring WebFlux 使用的ConversionService,则可以为WebFluxConfigurer bean 提供一个方法。addFormattersspring-doc.cn

还可以使用配置属性自定义转换。 如果未配置,则使用以下默认值:spring.webflux.format.*spring-doc.cn

财产 DateTimeFormatter 格式

spring.webflux.format.datespring-doc.cn

ofLocalizedDate(FormatStyle.SHORT)spring-doc.cn

java.util.DateLocalDatespring-doc.cn

spring.webflux.format.timespring-doc.cn

ofLocalizedTime(FormatStyle.SHORT)spring-doc.cn

java.time 的 LocalTimeOffsetTimespring-doc.cn

spring.webflux.format.date-timespring-doc.cn

ofLocalizedDateTime(FormatStyle.SHORT)spring-doc.cn

java.time 的 LocalDateTimeOffsetDateTimeZonedDateTimespring-doc.cn

使用 HttpMessageReaders 和 HttpMessageWriters 的 HTTP 编解码器

Spring WebFlux 使用HttpMessageReaderHttpMessageWriter接口来转换 HTTP 请求和响应。 它们使用 CodecConfigurer 进行配置,通过查看 Classpath 中可用的库来获得合理的默认值。spring-doc.cn

Spring Boot 为编解码器提供了专用的配置属性。 它还通过使用 CodecCustomizer 实例应用进一步的自定义。 例如,将配置键应用于 Jackson 编解码器。spring.codec.*spring.jackson.*spring-doc.cn

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

import org.springframework.boot.web.codec.CodecCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.codec.ServerSentEventHttpMessageReader;

@Configuration(proxyBeanMethods = false)
public class MyCodecsConfiguration {

	@Bean
	public CodecCustomizer myCodecCustomizer() {
		return (configurer) -> {
			configurer.registerDefaults(false);
			configurer.customCodecs().register(new ServerSentEventHttpMessageReader());
			// ...
		};
	}

}
import org.springframework.boot.web.codec.CodecCustomizer
import org.springframework.context.annotation.Bean
import org.springframework.http.codec.CodecConfigurer
import org.springframework.http.codec.ServerSentEventHttpMessageReader

class MyCodecsConfiguration {

	@Bean
	fun myCodecCustomizer(): CodecCustomizer {
		return CodecCustomizer { configurer: CodecConfigurer ->
			configurer.registerDefaults(false)
			configurer.customCodecs().register(ServerSentEventHttpMessageReader())
		}
	}

}

静态内容

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

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

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

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

除了前面列出的“标准”静态资源位置之外,Webjars 内容还有一个特殊情况。 默认情况下,如果 jar 文件以 Webjars 格式打包,则从 jar 文件提供任何具有路径 in 的资源。 可以使用 属性 自定义路径。/webjars/**spring.webflux.webjars-path-patternspring-doc.cn

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

欢迎页面

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

这仅充当应用程序定义的实际索引路由的回退。 排序由 HandlerMapping bean 的顺序定义,默认情况下如下:spring-doc.cn

org.springframework.web.reactive.function.server.support.RouterFunctionMappingspring-doc.cn

使用 RouterFunction bean 声明的端点spring-doc.cn

org.springframework.web.reactive.result.method.annotation.RequestMappingHandlerMappingspring-doc.cn

@Controller bean 中声明的端点spring-doc.cn

RouterFunctionMapping对于欢迎页面spring-doc.cn

欢迎页面支持spring-doc.cn

模板引擎

除了 REST Web 服务之外,您还可以使用 Spring WebFlux 来提供动态 HTML 内容。 Spring WebFlux 支持多种模板技术,包括 Thymeleaf、FreeMarker 和 Mustache。spring-doc.cn

Spring Boot 包括对以下模板引擎的自动配置支持:spring-doc.cn

当您将其中一个模板引擎与默认配置一起使用时,您的模板会自动从 中选取。src/main/resources/templatesspring-doc.cn

错误处理

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

在直接在 Spring Boot 中自定义错误处理之前,您可以利用 Spring WebFlux 中的 RFC 9457 问题详细信息支持。 Spring WebFlux 可以生成具有 media 类型的自定义错误消息,例如:application/problem+jsonspring-doc.cn

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

可以通过设置为 来启用此支持。spring.webflux.problemdetails.enabledtruespring-doc.cn

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

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

import reactor.core.publisher.Mono;

import org.springframework.boot.autoconfigure.web.WebProperties;
import org.springframework.boot.autoconfigure.web.reactive.error.AbstractErrorWebExceptionHandler;
import org.springframework.boot.web.reactive.error.ErrorAttributes;
import org.springframework.context.ApplicationContext;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.codec.ServerCodecConfigurer;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.function.server.RouterFunction;
import org.springframework.web.reactive.function.server.RouterFunctions;
import org.springframework.web.reactive.function.server.ServerRequest;
import org.springframework.web.reactive.function.server.ServerResponse;
import org.springframework.web.reactive.function.server.ServerResponse.BodyBuilder;

@Component
public class MyErrorWebExceptionHandler extends AbstractErrorWebExceptionHandler {

	public MyErrorWebExceptionHandler(ErrorAttributes errorAttributes, WebProperties webProperties,
			ApplicationContext applicationContext, ServerCodecConfigurer serverCodecConfigurer) {
		super(errorAttributes, webProperties.getResources(), applicationContext);
		setMessageReaders(serverCodecConfigurer.getReaders());
		setMessageWriters(serverCodecConfigurer.getWriters());
	}

	@Override
	protected RouterFunction<ServerResponse> getRoutingFunction(ErrorAttributes errorAttributes) {
		return RouterFunctions.route(this::acceptsXml, this::handleErrorAsXml);
	}

	private boolean acceptsXml(ServerRequest request) {
		return request.headers().accept().contains(MediaType.APPLICATION_XML);
	}

	public Mono<ServerResponse> handleErrorAsXml(ServerRequest request) {
		BodyBuilder builder = ServerResponse.status(HttpStatus.INTERNAL_SERVER_ERROR);
		// ... additional builder calls
		return builder.build();
	}

}
import org.springframework.boot.autoconfigure.web.WebProperties
import org.springframework.boot.autoconfigure.web.reactive.error.AbstractErrorWebExceptionHandler
import org.springframework.boot.web.reactive.error.ErrorAttributes
import org.springframework.context.ApplicationContext
import org.springframework.http.HttpStatus
import org.springframework.http.MediaType
import org.springframework.http.codec.ServerCodecConfigurer
import org.springframework.stereotype.Component
import org.springframework.web.reactive.function.server.RouterFunction
import org.springframework.web.reactive.function.server.RouterFunctions
import org.springframework.web.reactive.function.server.ServerRequest
import org.springframework.web.reactive.function.server.ServerResponse
import reactor.core.publisher.Mono

@Component
class MyErrorWebExceptionHandler(
		errorAttributes: ErrorAttributes, webProperties: WebProperties,
		applicationContext: ApplicationContext, serverCodecConfigurer: ServerCodecConfigurer
) : AbstractErrorWebExceptionHandler(errorAttributes, webProperties.resources, applicationContext) {

	init {
		setMessageReaders(serverCodecConfigurer.readers)
		setMessageWriters(serverCodecConfigurer.writers)
	}

	override fun getRoutingFunction(errorAttributes: ErrorAttributes): RouterFunction<ServerResponse> {
		return RouterFunctions.route(this::acceptsXml, this::handleErrorAsXml)
	}

	private fun acceptsXml(request: ServerRequest): Boolean {
		return request.headers().accept().contains(MediaType.APPLICATION_XML)
	}

	fun handleErrorAsXml(request: ServerRequest): Mono<ServerResponse> {
		val builder = ServerResponse.status(HttpStatus.INTERNAL_SERVER_ERROR)
		// ... additional builder calls
		return builder.build()
	}

}

为了获得更完整的图片,你还可以直接子类化DefaultErrorWebExceptionHandler并覆盖特定方法。spring-doc.cn

在某些情况下,Web 观测或指标基础设施不会记录在控制器级别处理的错误。 应用程序可以通过在观察上下文中设置已处理的异常来确保此类异常与观察一起记录。spring-doc.cn

自定义错误页面

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

例如,要映射到静态 HTML 文件,您的目录结构将如下所示:404spring-doc.cn

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

要使用 Mustache 模板映射所有错误,您的目录结构将如下所示:5xxspring-doc.cn

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

Web 过滤器

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

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

Web 过滤器 次序

WebFilterChainProxy(Spring Security)spring-doc.cn

-100spring-doc.cn

HttpExchangesWebFilterspring-doc.cn

Ordered.LOWEST_PRECEDENCE - 10spring-doc.cn

嵌入式反应式服务器支持

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

自定义 Reactive 服务器

常见的反应式 Web 服务器设置可以使用 Spring Environment 属性进行配置。 通常,您将在 or 文件中定义属性。application.propertiesapplication.yamlspring-doc.cn

常见的服务器设置包括:spring-doc.cn

Spring Boot 会尽可能多地公开通用设置,但这并不总是可能的。 对于这些情况,专用命名空间(如)提供特定于服务器的自定义。server.netty.*spring-doc.cn

有关完整列表,请参阅 ServerProperties 类。

编程自定义

如果需要以编程方式配置反应式 Web 服务器,则可以注册实现WebServerFactoryCustomizer接口的 Spring Bean。WebServerFactoryCustomizer提供对ConfigurableReactiveWebServerFactory的访问,其中包括许多自定义 setter 方法。 以下示例显示了以编程方式设置端口:spring-doc.cn

import org.springframework.boot.web.reactive.server.ConfigurableReactiveWebServerFactory;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.stereotype.Component;

@Component
public class MyWebServerFactoryCustomizer implements WebServerFactoryCustomizer<ConfigurableReactiveWebServerFactory> {

	@Override
	public void customize(ConfigurableReactiveWebServerFactory server) {
		server.setPort(9000);
	}

}
import org.springframework.boot.web.server.WebServerFactoryCustomizer
import org.springframework.boot.web.reactive.server.ConfigurableReactiveWebServerFactory
import org.springframework.stereotype.Component

@Component
class MyWebServerFactoryCustomizer : WebServerFactoryCustomizer<ConfigurableReactiveWebServerFactory> {

	override fun customize(server: ConfigurableReactiveWebServerFactory) {
		server.setPort(9000)
	}

}

JettyReactiveWebServerFactoryNettyReactiveWebServerFactoryTomcatReactiveWebServerFactoryUndertowReactiveWebServerFactoryConfigurableReactiveWebServerFactory 的专用变体,它们分别具有针对 Jetty、Reactor Netty、Tomcat 和 Undertow 的其他自定义设置器方法。 以下示例显示了如何自定义 NettyReactiveWebServerFactory,该 NettyReactiveWebServerFactory 提供对 Reactor Netty 特定配置选项的访问:spring-doc.cn

import java.time.Duration;

import org.springframework.boot.web.embedded.netty.NettyReactiveWebServerFactory;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.stereotype.Component;

@Component
public class MyNettyWebServerFactoryCustomizer implements WebServerFactoryCustomizer<NettyReactiveWebServerFactory> {

	@Override
	public void customize(NettyReactiveWebServerFactory factory) {
		factory.addServerCustomizers((server) -> server.idleTimeout(Duration.ofSeconds(20)));
	}

}
import org.springframework.boot.web.embedded.netty.NettyReactiveWebServerFactory
import org.springframework.boot.web.server.WebServerFactoryCustomizer
import org.springframework.stereotype.Component
import java.time.Duration

@Component
class MyNettyWebServerFactoryCustomizer : WebServerFactoryCustomizer<NettyReactiveWebServerFactory> {

	override fun customize(factory: NettyReactiveWebServerFactory) {
		factory.addServerCustomizers({ server -> server.idleTimeout(Duration.ofSeconds(20)) })
	}

}

直接自定义 ConfigurableReactiveWebServerFactory

对于需要你从ReactiveWebServerFactory扩展的更高级的用例,你可以自己公开这种类型的 bean。spring-doc.cn

为许多配置选项提供了 setter。 如果你需要做一些更奇特的事情,还提供了几个受保护的方法 “钩子”。 有关详细信息,请参见 ConfigurableReactiveWebServerFactory API 文档。spring-doc.cn

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

反应式服务器资源配置

在自动配置 Reactor Netty 或 Jetty 服务器时, Spring Boot 将创建特定的 bean,这些 bean 将向服务器实例提供 HTTP 资源:ReactorResourceFactoryJettyResourceFactoryspring-doc.cn

默认情况下,这些资源也将与 Reactor Netty 和 Jetty 客户端共享,以获得最佳性能,前提是:spring-doc.cn

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

您可以在 WebClient 运行时 部分了解有关客户端资源配置的更多信息。spring-doc.cn