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

响应式核心

spring-web 模块包含以下对响应式 Web 应用程序的基础支持:spring-doc.cadn.net.cn

HttpHandler

HttpHandler 是一个简单的契约,仅包含一个用于处理请求和响应的方法。它被有意设计得极为精简,其主要且唯一的目的就是对不同的 HTTP 服务器 API 提供一个最小化的抽象。spring-doc.cadn.net.cn

下表描述了所支持的服务器 API:spring-doc.cadn.net.cn

服务器名称 所使用的服务器 API 响应式流支持

Nettyspring-doc.cadn.net.cn

Netty APIspring-doc.cadn.net.cn

Reactor Nettyspring-doc.cadn.net.cn

Undertowspring-doc.cadn.net.cn

Undertow APIspring-doc.cadn.net.cn

spring-web:Undertow 到响应式流(Reactive Streams)的桥接spring-doc.cadn.net.cn

Tomcatspring-doc.cadn.net.cn

Servlet 非阻塞 I/O;Tomcat API 用于读写 ByteBuffer 与 byte[]spring-doc.cadn.net.cn

spring-web:Servlet 非阻塞 I/O 到响应式流(Reactive Streams)的桥接spring-doc.cadn.net.cn

Jettyspring-doc.cadn.net.cn

Servlet 非阻塞 I/O;Jetty API 写入 ByteBuffer 与 byte[] 的对比spring-doc.cadn.net.cn

spring-web:Servlet 非阻塞 I/O 到响应式流(Reactive Streams)的桥接spring-doc.cadn.net.cn

Servlet 容器spring-doc.cadn.net.cn

Servlet 非阻塞 I/Ospring-doc.cadn.net.cn

spring-web:Servlet 非阻塞 I/O 到响应式流(Reactive Streams)的桥接spring-doc.cadn.net.cn

下表描述了服务器依赖项(另请参阅支持的版本):spring-doc.cadn.net.cn

服务器名称 组 ID 构件名称

Reactor Nettyspring-doc.cadn.net.cn

io.projectreactor.nettyspring-doc.cadn.net.cn

reactor-nettyspring-doc.cadn.net.cn

Undertowspring-doc.cadn.net.cn

io.undertowspring-doc.cadn.net.cn

undertow-corespring-doc.cadn.net.cn

Tomcatspring-doc.cadn.net.cn

org.apache.tomcat.embedspring-doc.cadn.net.cn

tomcat-embed-corespring-doc.cadn.net.cn

Jettyspring-doc.cadn.net.cn

org.eclipse.jettyspring-doc.cadn.net.cn

jetty-server、jetty-servletspring-doc.cadn.net.cn

下面的代码片段展示了如何将 HttpHandler 适配器与各个服务器 API 一起使用:spring-doc.cadn.net.cn

Reactor Nettyspring-doc.cadn.net.cn

HttpHandler handler = ...
ReactorHttpHandlerAdapter adapter = new ReactorHttpHandlerAdapter(handler);
HttpServer.create().host(host).port(port).handle(adapter).bindNow();
val handler: HttpHandler = ...
val adapter = ReactorHttpHandlerAdapter(handler)
HttpServer.create().host(host).port(port).handle(adapter).bindNow()
HttpHandler handler = ...
UndertowHttpHandlerAdapter adapter = new UndertowHttpHandlerAdapter(handler);
Undertow server = Undertow.builder().addHttpListener(port, host).setHandler(adapter).build();
server.start();
val handler: HttpHandler = ...
val adapter = UndertowHttpHandlerAdapter(handler)
val server = Undertow.builder().addHttpListener(port, host).setHandler(adapter).build()
server.start()
HttpHandler handler = ...
Servlet servlet = new TomcatHttpHandlerAdapter(handler);

Tomcat server = new Tomcat();
File base = new File(System.getProperty("java.io.tmpdir"));
Context rootContext = server.addContext("", base.getAbsolutePath());
Tomcat.addServlet(rootContext, "main", servlet);
rootContext.addServletMappingDecoded("/", "main");
server.setHost(host);
server.setPort(port);
server.start();
val handler: HttpHandler = ...
val servlet = TomcatHttpHandlerAdapter(handler)

val server = Tomcat()
val base = File(System.getProperty("java.io.tmpdir"))
val rootContext = server.addContext("", base.absolutePath)
Tomcat.addServlet(rootContext, "main", servlet)
rootContext.addServletMappingDecoded("/", "main")
server.host = host
server.setPort(port)
server.start()
HttpHandler handler = ...
Servlet servlet = new JettyHttpHandlerAdapter(handler);

Server server = new Server();
ServletContextHandler contextHandler = new ServletContextHandler(server, "");
contextHandler.addServlet(new ServletHolder(servlet), "/");
contextHandler.start();

ServerConnector connector = new ServerConnector(server);
connector.setHost(host);
connector.setPort(port);
server.addConnector(connector);
server.start();
val handler: HttpHandler = ...
val servlet = JettyHttpHandlerAdapter(handler)

val server = Server()
val contextHandler = ServletContextHandler(server, "")
contextHandler.addServlet(ServletHolder(servlet), "/")
contextHandler.start();

val connector = ServerConnector(server)
connector.host = host
connector.port = port
server.addConnector(connector)
server.start()

Servlet 容器spring-doc.cadn.net.cn

若要作为 WAR 部署到任何 Servlet 容器,您可以扩展并包含 AbstractReactiveWebInitializer 到 WAR 中。该类使用 ServletHttpHandlerAdapter 包装一个 HttpHandler, 并将其注册为 Servletspring-doc.cadn.net.cn

WebHandlerAPI

org.springframework.web.server 包基于 HttpHandler 契约构建,提供了一个通用的 Web API,用于通过由多个 WebExceptionHandler、多个 WebFilter 以及单个 WebHandler 组件组成的链来处理请求。该链可以通过 WebHttpHandlerBuilder 进行组装,只需指向一个 Spring ApplicationContext(其中的组件会被 自动检测),和/或通过向构建器注册组件来完成。spring-doc.cadn.net.cn

虽然 HttpHandler 的目标很简单,即抽象化不同 HTTP 服务器的使用,但 WebHandler API 旨在提供更广泛的功能集,这些功能通常用于 Web 应用程序中,例如:spring-doc.cadn.net.cn

特殊 Bean 类型

下表列出了 WebHttpHandlerBuilder 可以在 Spring ApplicationContext 中自动检测到的组件,或者可以直接向其注册的组件:spring-doc.cadn.net.cn

Bean 名称 Bean 类型 计数 <description> </description>

<any>spring-doc.cadn.net.cn

WebExceptionHandlerspring-doc.cadn.net.cn

0..Nspring-doc.cadn.net.cn

为来自 WebFilter 实例链和目标 WebHandler 的异常提供处理。更多详情,请参阅异常spring-doc.cadn.net.cn

<any>spring-doc.cadn.net.cn

WebFilterspring-doc.cadn.net.cn

0..Nspring-doc.cadn.net.cn

将拦截风格的逻辑应用于过滤器链其余部分以及目标 WebHandler 的前后。更多详情,请参见过滤器spring-doc.cadn.net.cn

webHandlerspring-doc.cadn.net.cn

WebHandlerspring-doc.cadn.net.cn

1spring-doc.cadn.net.cn

请求的处理器。spring-doc.cadn.net.cn

webSessionManagerspring-doc.cadn.net.cn

WebSessionManagerspring-doc.cadn.net.cn

0..1spring-doc.cadn.net.cn

通过 WebSession 上的一个方法暴露的 ServerWebExchange 实例的管理器。 默认为 DefaultWebSessionManagerspring-doc.cadn.net.cn

serverCodecConfigurerspring-doc.cadn.net.cn

ServerCodecConfigurerspring-doc.cadn.net.cn

0..1spring-doc.cadn.net.cn

用于访问 HttpMessageReader 实例,以解析表单数据和多部分(multipart)数据,这些数据随后通过 ServerWebExchange 上的方法暴露出来。默认情况下由 ServerCodecConfigurer.create() 提供。spring-doc.cadn.net.cn

localeContextResolverspring-doc.cadn.net.cn

LocaleContextResolverspring-doc.cadn.net.cn

0..1spring-doc.cadn.net.cn

通过 LocaleContext 上的一个方法暴露的 ServerWebExchange 解析器。 默认为 AcceptHeaderLocaleContextResolverspring-doc.cadn.net.cn

forwardedHeaderTransformerspring-doc.cadn.net.cn

ForwardedHeaderTransformerspring-doc.cadn.net.cn

0..1spring-doc.cadn.net.cn

用于处理转发类型(forwarded type)的头部信息,可以提取并移除这些头部,也可以仅移除它们。 默认情况下不使用。spring-doc.cadn.net.cn

表单数据

ServerWebExchange 提供了以下方法用于访问表单数据:spring-doc.cadn.net.cn

Mono<MultiValueMap<String, String>> getFormData();
suspend fun getFormData(): MultiValueMap<String, String>

DefaultServerWebExchange 使用配置好的 HttpMessageReader 将表单数据(application/x-www-form-urlencoded)解析为一个 MultiValueMap。默认情况下,FormHttpMessageReaderServerCodecConfigurer bean 进行配置(参见Web Handler API)。spring-doc.cadn.net.cn

多部分数据

ServerWebExchange 提供了以下方法用于访问多部分(multipart)数据:spring-doc.cadn.net.cn

Mono<MultiValueMap<String, Part>> getMultipartData();
suspend fun getMultipartData(): MultiValueMap<String, Part>

DefaultServerWebExchange 使用配置的 HttpMessageReader<MultiValueMap<String, Part>>multipart/form-datamultipart/mixedmultipart/related 内容解析为 MultiValueMap。 默认情况下,这是 DefaultPartHttpMessageReader,它没有任何第三方依赖项。 或者,也可以使用基于 Synchronoss NIO Multipart 库的 SynchronossPartHttpMessageReader。 两者均通过 ServerCodecConfigurer Bean 进行配置(请参阅 Web Handler API)。spring-doc.cadn.net.cn

要以流式方式解析 multipart 数据,您可以使用 Flux<PartEvent> 返回的 PartEventHttpMessageReader,而不是使用 @RequestPart。因为 Map 意味着通过名称对各个部分进行类似 @RequestBody 的访问,因此需要完整地解析整个 multipart 数据。 相比之下,您可以使用 Flux<PartEvent> 将内容解码为 MultiValueMap,而无需将其收集到 7 中。spring-doc.cadn.net.cn

转发的请求头

当请求经过代理(例如负载均衡器)时,主机、端口和协议方案可能会发生变化。这从客户端的角度来看,使得创建指向正确主机、端口和协议方案的链接变得具有挑战性。spring-doc.cadn.net.cn

RFC 7239 定义了 Forwarded HTTP 头部, 代理可以使用该头部提供有关原始请求的信息。此外,还存在其他 非标准的头部,包括 X-Forwarded-HostX-Forwarded-PortX-Forwarded-ProtoX-Forwarded-SslX-Forwarded-Prefixspring-doc.cadn.net.cn

ForwardedHeaderTransformer 是一个组件,它根据转发头(forwarded headers)修改请求的主机、端口和协议(scheme),然后移除这些头信息。如果你将其声明为名为 forwardedHeaderTransformer 的 Bean,它将被自动检测并使用。spring-doc.cadn.net.cn

转发头(forwarded headers)存在安全方面的考虑,因为应用程序无法判断这些头是由代理按预期添加的,还是由恶意客户端伪造的。因此,在信任边界处的代理应配置为移除来自外部的不可信转发流量。你也可以将 ForwardedHeaderTransformer 配置为 removeOnly=true,在这种情况下,它会移除这些头但不会使用它们。spring-doc.cadn.net.cn

在 5.1 版本中,ForwardedHeaderFilter 已被弃用,并由 ForwardedHeaderTransformer 取代,以便在创建 exchange 之前更早地处理转发头信息。如果仍然配置了该过滤器,它将从过滤器列表中移除,并改用 ForwardedHeaderTransformer

过滤器

WebHandler API 中,您可以使用 WebFilter 在过滤器链的其余部分和目标 WebHandler 处理之前和之后应用拦截式逻辑。当使用 WebFlux 配置 时,注册 WebFilter 非常简单,只需将其声明为 Spring Bean,并(可选地)通过在 Bean 声明上使用 @Order 或实现 Ordered 来表达优先级。spring-doc.cadn.net.cn

跨域资源共享(CORS)

Spring WebFlux 通过控制器上的注解提供了细粒度的 CORS 配置支持。然而,当你将其与 Spring Security 一起使用时,我们建议依赖内置的 CorsFilter,该过滤器必须排在 Spring Security 过滤器链之前。spring-doc.cadn.net.cn

请参阅关于 CORS 的章节以及 CORS WebFilter 以获取更多详细信息。spring-doc.cadn.net.cn

异常

WebHandler API 中,您可以使用 WebExceptionHandler 来处理来自 WebFilter 实例链和目标 WebHandler 的异常。当使用 WebFlux 配置 时,注册 WebExceptionHandler 非常简单,只需将其声明为 Spring Bean,并(可选地)通过在 Bean 声明上使用 @Order 或实现 Ordered 来表达优先级。spring-doc.cadn.net.cn

下表描述了可用的 WebExceptionHandler 实现:spring-doc.cadn.net.cn

异常处理器 <description> </description>

ResponseStatusExceptionHandlerspring-doc.cadn.net.cn

提供对类型为 ResponseStatusException 的异常的处理,方法是将响应设置为该异常的 HTTP 状态码。spring-doc.cadn.net.cn

WebFluxResponseStatusExceptionHandlerspring-doc.cadn.net.cn

ResponseStatusExceptionHandler 的扩展,还可以确定任何异常上 @ResponseStatus 注解所指定的 HTTP 状态码。spring-doc.cadn.net.cn

此处理器在WebFlux 配置中声明。spring-doc.cadn.net.cn

编解码器

spring-webspring-core 模块通过带有响应式流(Reactive Streams)背压机制的非阻塞 I/O,提供了将字节内容与高层对象之间进行序列化和反序列化的支持。以下内容描述了该支持:spring-doc.cadn.net.cn

spring-core 模块提供了 byte[]ByteBufferDataBufferResourceString 的编码器和解码器实现。spring-web 模块则提供了 Jackson JSON、Jackson Smile、JAXB2、Protocol Buffers 等编码器和解码器,以及仅用于 Web 的 HTTP 消息读取器和写入器实现,用于处理表单数据、多部分(multipart)内容、服务器发送事件(server-sent events)等。spring-doc.cadn.net.cn

ClientCodecConfigurerServerCodecConfigurer 通常用于配置和自定义应用程序中使用的编解码器。请参阅有关配置HTTP 消息编解码器的部分。spring-doc.cadn.net.cn

Jackson JSON

当 Jackson 库存在时,JSON 和二进制 JSON(Smile)均受支持。spring-doc.cadn.net.cn

Jackson2Decoder 的工作方式如下:spring-doc.cadn.net.cn

  • Jackson 的异步、非阻塞解析器用于将字节块流聚合为多个 TokenBuffer,每个 1 代表一个 JSON 对象。spring-doc.cadn.net.cn

  • 每个 TokenBuffer 都会被传递给 Jackson 的 ObjectMapper,以创建一个更高层次的对象。spring-doc.cadn.net.cn

  • 当解码为单值发布者(例如 Mono)时,只有一个 TokenBufferspring-doc.cadn.net.cn

  • 在解码为多值发布者(例如 Flux)时,一旦接收到足够构成一个完整对象的字节,每个 TokenBuffer 就会立即传递给 ObjectMapper。输入内容可以是一个 JSON 数组,也可以是任意 行分隔的 JSON 格式,例如 NDJSON、 JSON Lines 或 JSON 文本序列。spring-doc.cadn.net.cn

Jackson2Encoder 的工作方式如下:spring-doc.cadn.net.cn

  • 对于单值发布者(例如 Mono),只需通过 ObjectMapper 将其序列化即可。spring-doc.cadn.net.cn

  • 对于具有 application/json 类型的多值发布者,默认使用 Flux#collectToList() 收集所有值,然后对生成的集合进行序列化。spring-doc.cadn.net.cn

  • 对于具有流式媒体类型(例如 application/x-ndjsonapplication/stream+x-jackson-smile)的多值发布者,请使用行分隔 JSON 格式对每个值分别进行编码、写入和刷新。其他流式媒体类型也可以向编码器注册。spring-doc.cadn.net.cn

  • 对于 SSE,每次事件都会调用 Jackson2Encoder,并且会刷新输出以确保及时传递。spring-doc.cadn.net.cn

默认情况下,Jackson2EncoderJackson2Decoder 都不支持 String 类型的元素。相反,默认假定字符串或字符串序列代表已序列化的 JSON 内容,应由 CharSequenceEncoder 进行渲染。如果你需要从 Flux<String> 渲染一个 JSON 数组,请使用 Flux#collectToList() 并编码为 Mono<List<String>>spring-doc.cadn.net.cn

表单数据

FormHttpMessageReaderFormHttpMessageWriter 支持解码和编码 application/x-www-form-urlencoded 内容。spring-doc.cadn.net.cn

在服务器端,当需要从多个位置访问表单内容时, ServerWebExchange 提供了一个专用的 getFormData() 方法,该方法通过 FormHttpMessageReader 解析内容, 然后缓存结果以便重复访问。 请参阅 表单数据,位于 WebHandler API 部分。spring-doc.cadn.net.cn

一旦使用了 getFormData(),就无法再从请求体中读取原始的原始内容。因此,应用程序应始终通过 ServerWebExchange 来访问缓存的表单数据,而不是直接读取原始请求体。spring-doc.cadn.net.cn

多部分(Multipart)

MultipartHttpMessageReaderMultipartHttpMessageWriter 支持解码和编码"multipart/form-data"、"multipart/mixed"以及"multipart/related"内容。 随后,MultipartHttpMessageReader 将实际解析工作委托给另一个 HttpMessageReader,将其解析为 Flux<Part>,然后简单地将各部分收集到 MultiValueMap 中。 默认情况下,使用的是 DefaultPartHttpMessageReader,但可以通过 ServerCodecConfigurer 进行更改。 有关 DefaultPartHttpMessageReader 的更多信息,请参阅 DefaultPartHttpMessageReader 的 Javadocspring-doc.cadn.net.cn

在服务器端,当需要从多个位置访问多部分表单内容时,ServerWebExchange 提供了专用的 getMultipartData() 方法,该方法通过 MultipartHttpMessageReader 解析内容,然后缓存结果以供重复访问。 请参阅 WebHandler API 章节中的 多部分数据spring-doc.cadn.net.cn

一旦使用了 getMultipartData(),就无法再从请求体中读取原始的原始内容。因此,应用程序必须始终一致地使用 getMultipartData() 来实现对各部分(parts)的重复、类似 Map 的访问;否则,应依赖 SynchronossPartHttpMessageReaderFlux<Part> 进行一次性访问。spring-doc.cadn.net.cn

限制

可以为那些对部分或全部输入流进行缓冲的 DecoderHttpMessageReader 实现配置一个内存中缓冲字节数的最大限制。 在某些情况下,缓冲的发生是因为输入被聚合并表示为单个对象——例如,带有 @RequestBody byte[] 的控制器方法、x-www-form-urlencoded 数据等。 在流式处理场景中,当对输入流进行拆分时(例如,分隔符分隔的文本、JSON 对象流等),也会发生缓冲。 对于这些流式处理的情况,该限制适用于流中单个对象所关联的字节数。spring-doc.cadn.net.cn

要配置缓冲区大小,您可以检查给定的 DecoderHttpMessageReader 是否公开了 maxInMemorySize 属性,如果公开了该属性,其 Javadoc 中将包含有关默认值的详细信息。在服务器端,ServerCodecConfigurer 提供了一个统一的位置来设置所有编解码器,请参阅HTTP 消息编解码器。在客户端,所有编解码器的限制可以在WebClient.Builder 中进行修改。spring-doc.cadn.net.cn

对于多部分(Multipart)解析maxInMemorySize 属性用于限制非文件部分的大小。对于文件部分,该属性决定了将该部分写入磁盘的阈值。对于写入磁盘的文件部分,还有一个额外的 maxDiskUsagePerPart 属性,用于限制每个部分所占用的磁盘空间。此外,还有一个 maxParts 属性,用于限制多部分请求中各部分的总数量。 在 WebFlux 中配置上述三个属性时,你需要向 MultipartHttpMessageReader 提供一个预先配置好的 ServerCodecConfigurer 实例。spring-doc.cadn.net.cn

流式处理

在向 HTTP 响应进行流式传输时(例如 text/event-streamapplication/x-ndjson),定期发送数据非常重要,以便能够更早而非更晚地可靠检测到客户端断开连接。这种发送可以是一个仅包含注释的空 SSE 事件,或者任何其他实际上可作为心跳机制的“无操作”(no-op)数据。spring-doc.cadn.net.cn

DataBuffer

DataBuffer 是 WebFlux 中字节缓冲区的表示形式。有关此内容的更多详细信息,请参阅本参考文档 Spring Core 部分中的数据缓冲区和编解码器一节。需要理解的关键点是,在某些服务器(如 Netty)上,字节缓冲区是经过池化并采用引用计数的,必须在使用完毕后予以释放,以避免内存泄漏。spring-doc.cadn.net.cn

WebFlux 应用程序通常无需关注此类问题,除非它们直接消费或生成数据缓冲区(而不是依赖编解码器在高层对象与数据之间进行转换),或者除非它们选择创建自定义编解码器。对于这些情况,请参阅数据缓冲区和编解码器中的相关信息,特别是使用 DataBuffer一节。spring-doc.cadn.net.cn

日志记录

DEBUG 级别的日志记录在 Spring WebFlux 中设计得简洁、精炼且对人类友好。它聚焦于那些反复有用的关键信息,而非仅在调试特定问题时才有用的其他信息。spring-doc.cadn.net.cn

TRACE 级别的日志记录通常遵循与 DEBUG 相同的原则(例如,也不应像“消防水带”一样输出大量日志),但可用于调试任何问题。此外,某些日志消息在 TRACE 级别下可能会比在 DEBUG 级别下显示更详细的细节。spring-doc.cadn.net.cn

良好的日志记录源于使用日志的经验。如果您发现任何不符合所述目标的内容,请告知我们。spring-doc.cadn.net.cn

日志 ID

在 WebFlux 中,单个请求可能会在多个线程上执行,因此线程 ID 对于关联属于特定请求的日志消息并无帮助。这就是为什么 WebFlux 的日志消息默认会加上一个请求专属的 ID 作为前缀。spring-doc.cadn.net.cn

在服务器端,日志 ID 存储在 ServerWebExchange 属性中 (LOG_ID_ATTRIBUTE), 而基于该 ID 的完整格式化前缀可从 ServerWebExchange#getLogPrefix() 获取。在 WebClient 端,日志 ID 存储在 ClientRequest 属性中 (LOG_ID_ATTRIBUTE) ,而完整的格式化前缀可从 ClientRequest#logPrefix() 获取。spring-doc.cadn.net.cn

敏感数据

DEBUGTRACE 日志记录可能会记录敏感信息。因此,表单参数和请求头默认会被屏蔽,您必须显式启用才能完整记录它们。spring-doc.cadn.net.cn

以下示例展示了如何对服务器端请求进行此操作:spring-doc.cadn.net.cn

@Configuration
@EnableWebFlux
class MyConfig implements WebFluxConfigurer {

	@Override
	public void configureHttpMessageCodecs(ServerCodecConfigurer configurer) {
		configurer.defaultCodecs().enableLoggingRequestDetails(true);
	}
}
@Configuration
@EnableWebFlux
class MyConfig : WebFluxConfigurer {

	override fun configureHttpMessageCodecs(configurer: ServerCodecConfigurer) {
		configurer.defaultCodecs().enableLoggingRequestDetails(true)
	}
}

以下示例展示了如何对客户端请求进行此操作:spring-doc.cadn.net.cn

Consumer<ClientCodecConfigurer> consumer = configurer ->
		configurer.defaultCodecs().enableLoggingRequestDetails(true);

WebClient webClient = WebClient.builder()
		.exchangeStrategies(strategies -> strategies.codecs(consumer))
		.build();
val consumer: (ClientCodecConfigurer) -> Unit  = { configurer -> configurer.defaultCodecs().enableLoggingRequestDetails(true) }

val webClient = WebClient.builder()
		.exchangeStrategies({ strategies -> strategies.codecs(consumer) })
		.build()

追加器

像 SLF4J 和 Log4J 2 这样的日志记录库提供了异步记录器,以避免阻塞。尽管这些异步记录器自身也存在一些缺点,例如可能会丢弃那些无法加入日志队列的消息,但它们目前仍是响应式、非阻塞应用程序中可用的最佳选择。spring-doc.cadn.net.cn

自定义编解码器

应用程序可以注册自定义编解码器,以支持额外的媒体类型,或实现默认编解码器不支持的特定行为。spring-doc.cadn.net.cn

开发人员指定的某些配置选项会被强制应用到默认编解码器上。 自定义编解码器可能希望有机会与这些偏好设置保持一致, 例如强制实施缓冲限制记录敏感数据spring-doc.cadn.net.cn

以下示例展示了如何对客户端请求进行此操作:spring-doc.cadn.net.cn

WebClient webClient = WebClient.builder()
		.codecs(configurer -> {
				CustomDecoder decoder = new CustomDecoder();
                   configurer.customCodecs().registerWithDefaultConfig(decoder);
		})
		.build();
val webClient = WebClient.builder()
		.codecs({ configurer ->
				val decoder = CustomDecoder()
           		configurer.customCodecs().registerWithDefaultConfig(decoder)
		 })
		.build()