对于最新稳定版本,请使用Spring Boot 4.0.0spring-doc.cadn.net.cn

响应式网页应用

Spring Boot 通过为 Spring Webflux 提供自动配置,简化了响应式网页应用的开发。spring-doc.cadn.net.cn

“Spring WebFlux框架”

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

Spring WebFlux 有两种版本:功能型和基于注释型。 基于注释的模型与Spring MVC模型非常接近,如下示例所示:spring-doc.cadn.net.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 框架的一部分,详细信息可见其参考文档spring-doc.cadn.net.cn

“WebFlux.fn”功能变体将路由配置与实际请求处理分离,如下示例所示:spring-doc.cadn.net.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框架的一部分,详细信息可见于其参考文档中。spring-doc.cadn.net.cn

你可以定义多少路由器功能豆子,你喜欢模块化路由器的定义。 如果需要优先顺序,可以订购Beans。

要开始,请添加Spring BootStarters网流模块。spring-doc.cadn.net.cn

两者都加入Spring Boot启动网Spring BootStarters网流你应用中的模块是 Spring Boot 自动配置 Spring MVC,而不是 WebFlux。 之所以选择这种行为,是因为许多 Spring 开发者会添加Spring BootStarters网流使用响应式Web客户端. 你仍然可以通过设置所选应用类型来强制执行你的选择SpringApplication.setWebApplicationType(WebApplicationType.REACTIVE).

Spring WebFlux 自动配置

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

自动配置在 Spring 默认设置基础上增加了以下功能:spring-doc.cadn.net.cn

如果你想保留 Spring Boot 的 WebFlux 功能,并且想添加额外的 WebFlux 配置,你可以自己添加@Configuration类型类别WebFluxConfigurer没有 @EnableWebFlux.spring-doc.cadn.net.cn

如果你想在自动配置中增加额外的自定义功能HttpHandler,你可以定义类型的豆子WebHttpHandlerBuilderCustomizer并用它们来修改WebHttpHandlerBuilder.spring-doc.cadn.net.cn

如果你想完全掌控Spring WebFlux,可以添加自己的@Configuration注释为@EnableWebFlux.spring-doc.cadn.net.cn

Spring WebFlux 转换服务

如果你想自定义转换服务Spring WebFlux 使用,你可以提供WebFluxConfigurer带有addFormatters方法。spring-doc.cadn.net.cn

转换也可以通过以下方式进行定制spring.webflux.format.*配置属性。 未配置时,使用以下默认值:spring-doc.cadn.net.cn

属性 DateTimeFormatter 格式

春季.webflux.format.datespring-doc.cadn.net.cn

ofLocalizedDate(FormatStyle.SHORT)spring-doc.cadn.net.cn

java.util.Date本地日期spring-doc.cadn.net.cn

Spring.webflux.format.timespring-doc.cadn.net.cn

ofLocalizedTime(FormatStyle.SHORT)spring-doc.cadn.net.cn

java.time的本地时间偏移时间spring-doc.cadn.net.cn

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

ofLocalizedDateTime(FormatStyle.SHORT)spring-doc.cadn.net.cn

java.time的本地日期时间,偏移日期时间ZonedDateTimespring-doc.cadn.net.cn

带有 HttpMessageReaders 和 HttpMessageWriters 的 HTTP 编解码器

Spring WebFlux 使用HttpMessageReaderHttpMessageWriter用于转换HTTP请求和响应的接口。 它们配置为CodecConfigurer通过查看类路径中的库来制定合理的默认值。spring-doc.cadn.net.cn

Spring Boot 为编解码器提供了专用的配置属性,spring.codec.*. 它还通过以下方式进行进一步的自定义CodecCustomizer实例。 例如Spring。Jackson。*配置键被应用到Jackson编解码器上。spring-doc.cadn.net.cn

如果你需要添加或自定义编解码器,可以创建一个自定义的CodecCustomizer组件,如下例所示:spring-doc.cadn.net.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 中。 它使用ResourceWebHandler从Spring WebFlux下载,这样你可以通过添加自己的行为来修改该行为WebFluxConfigurer并且覆盖addResourceHandlers方法。spring-doc.cadn.net.cn

默认情况下,资源映射在 ,但你可以通过设置/**春网通量静态路径模式财产。 例如,将所有资源重新定位到/资源/**可以实现如下:spring-doc.cadn.net.cn

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

你也可以通过以下方式自定义静态资源位置spring.web.resources.static-locations. 这样做会将默认值替换为目录位置列表。 如果这样做,默认的欢迎页面检测会切换到你的自定义位置。 所以,如果存在index.html在你任何一个启动地点,它都是应用的主页。spring-doc.cadn.net.cn

除了前面提到的“标准”静态资源位置外,Webjars 内容还有一个特殊情况。 默认情况下,任何路径在 的资源/webjars/ **如果 jar 文件以 Webjars 格式打包,则 是从 jar 文件中提供。路径可以通过春.webflux.webjars-path-pattern财产。spring-doc.cadn.net.cn

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

欢迎页

Spring Boot 支持静态和模板欢迎页。它首先会寻找index.html文件在配置好的静态内容位置中。如果找不到,则会寻找指数模板。 如果找到其中任何一个,它会自动作为申请的欢迎页面使用。spring-doc.cadn.net.cn

这仅作为应用程序实际定义的索引路由的后备。排序由处理器映射豆子默认如下:spring-doc.cadn.net.cn

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

端点声明为路由器功能spring-doc.cadn.net.cn

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

@Controllerspring-doc.cadn.net.cn

RouterFunctionMapping欢迎页spring-doc.cadn.net.cn

欢迎页面支持spring-doc.cadn.net.cn

模板引擎

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

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

当你使用这些模板引擎中的默认配置时,模板会自动从以下获取src/main/resources/模板.spring-doc.cadn.net.cn

错误处理

Spring靴提供了WebExceptionHandler这样能合理处理所有错误。 它在处理顺序中的位置紧接WebFlux提供的处理程序,这些处理程序被视为最后。 对于机器客户端,它会生成包含错误信息、HTTP 状态和异常消息的 JSON 响应。 对于浏览器客户端,有一个“白标”错误处理程序,可以将相同数据渲染成HTML格式。 你也可以提供自己的HTML模板来显示错误(见下一节)。spring-doc.cadn.net.cn

在直接自定义 Spring Boot 的错误处理之前,你可以利用 Spring WebFlux 中的 RFC 9457 问题详情支持。 Spring WebFlux 可以生成自定义错误信息,包括application/problem+json媒体类型,比如:spring-doc.cadn.net.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.enabledtrue.spring-doc.cadn.net.cn

定制此功能的第一步通常是使用现有机制,但替换或增强错误内容。 为此,你可以添加一颗 类型的豆子错误属性.spring-doc.cadn.net.cn

要改变错误处理行为,你可以实现ErrorWebExceptionHandler并注册该类型的豆子定义。 因为ErrorWebExceptionHandler这个等级相当低,Spring靴也提供了方便的抽象错误WebExceptionHandler以便你能以WebFlux函数式的方式处理错误,如下示例所示:spring-doc.cadn.net.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()
	}

}

为了更完整的情况,你也可以选择子职业默认错误网页例外处理器直接覆盖特定方法。spring-doc.cadn.net.cn

在某些情况下,控制器级别处理的错误不会被网络观测或度量基础设施记录。应用程序可以通过在观测上下文中设置处理异常,确保这些异常与观测值一起被记录。spring-doc.cadn.net.cn

自定义错误页面

如果你想为某个状态码显示自定义的 HTML 错误页面,可以添加由错误/*,例如通过向/错误目录。 错误页面可以是静态 HTML(即添加到任何静态资源目录下),也可以用模板构建。 文件名称应为准确的状态码、状态码系列掩码,或错误如果其他条件匹配,默认情况下也没问题。 注意,通往默认误差视图的路径为错误/错误而 Spring MVC 的默认错误视图是错误.spring-doc.cadn.net.cn

例如,映射404对于静态HTML文件,你的目录结构如下:spring-doc.cadn.net.cn

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

映射所有5xx使用Mustache模板时,你的目录结构如下:spring-doc.cadn.net.cn

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

网页过滤器

Spring WebFlux 提供了WebFilter可以实现用于过滤HTTP请求-响应交换的接口。WebFilter应用上下文中发现的豆子会自动用于过滤每次交换。spring-doc.cadn.net.cn

如果Filter的顺序很重要,他们可以实现命令或者注释为@Order. Spring Boot 自动配置可能会帮你配置网页过滤器。 当它这样做时,将使用下表所示的顺序:spring-doc.cadn.net.cn

网页过滤 次序

WebFilterChainProxy(春季安全)spring-doc.cadn.net.cn

-100spring-doc.cadn.net.cn

HttpExchangesWebFilterspring-doc.cadn.net.cn

Ordered.LOWEST_PRECEDENCE - 10spring-doc.cadn.net.cn

嵌入式响应式服务器支持

Spring Boot 支持以下嵌入式响应式 Web 服务器:Reactor Netty、Tomcat、Jetty 和 Undertow。 大多数开发者会使用相应的起始程序来获得一个完全配置好的实例。 默认情况下,嵌入式服务器会监听8080端口上的HTTP请求。spring-doc.cadn.net.cn

定制响应式服务器

常见的响应式网页服务器设置可以通过 Spring 进行配置环境性能。 通常,你会定义application.propertiesapplication.yaml文件。spring-doc.cadn.net.cn

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

Spring Boot 尽力暴露常见设置,但这并不总是可行。 在这种情况下,专用命名空间如server.netty.*提供服务器专属定制。spring-doc.cadn.net.cn

参见ServerProperties完整列表。

程序化定制

如果你需要程序化配置你的响应式网页服务器,你可以注册一个实现WebServerFactoryCustomizer接口。WebServerFactoryCustomizer提供访问ConfigurableReactiveWebServerFactory其中包含多种自定义设置器方法。 以下示例展示了程序化设置端口:spring-doc.cadn.net.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)
	}

}

JettyReactiveWebServerFactory,NettyReactiveWebServerFactory,TomcatReactiveWebServerFactoryUndertowReactiveWebServerFactory是 的专用变体ConfigurableReactiveWebServerFactory分别为Jetty、Reactor Netty、Tomcat和Undertow提供了额外的自定义设定方法。 以下示例展示了如何自定义NettyReactiveWebServerFactory提供针对Reactor Netty的专属配置选项:spring-doc.cadn.net.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)) })
	}

}

直接自定义可配置的ReactiveWebServerFactory

对于需要扩展的高级用例ReactiveWebServerFactory你自己可以暴露出这种类型的豆子。spring-doc.cadn.net.cn

设置杆提供多种配置选项。 如果你想做一些更特别的事情,游戏还提供了几个安全的“钩子”。 参见ConfigurableReactiveWebServerFactory详细信息请参考API文档。spring-doc.cadn.net.cn

自动配置的自定义工具仍然会应用到你的自定义工厂,所以要谨慎使用这个选项。

响应式服务器资源配置

在自动配置 Reactor Netty 或 Jetty 服务器时,Spring Boot 会创建特定的 BEANS,为服务器实例提供 HTTP 资源:反应堆资源工厂Jetty资源工厂.spring-doc.cadn.net.cn

默认情况下,这些资源也会与反应堆Netty和Jetty客户端共享,以实现最佳性能,满足以下条件:spring-doc.cadn.net.cn

开发者可以通过提供自定义配置来覆盖Jetty和Reactor Netty的资源配置反应堆资源工厂Jetty资源工厂BEAN - 这将同时应用于客户端和服务器。spring-doc.cadn.net.cn

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