Configuration
创建 WebClient
最简单的方法是通过静态工厂方法之一:
The simplest way to create a WebClient
is through one of the static factory methods:
-
WebClient.create()
-
WebClient.create(String baseUrl)
此外,你还可以使用 WebClient.builder()
加上其他选项:
You can also use WebClient.builder()
with further options:
-
uriBuilderFactory
: CustomizedUriBuilderFactory
to use as a base URL. -
defaultUriVariables
: default values to use when expanding URI templates. -
defaultHeader
: Headers for every request. -
defaultCookie
: Cookies for every request. -
defaultRequest
:Consumer
to customize every request. -
filter
: Client filter for every request. -
exchangeStrategies
: HTTP message reader/writer customizations. -
clientConnector
: HTTP client library settings. -
observationRegistry
: the registry to use for enabling Observability support. -
observationConvention
: an optional, custom convention to extract metadata for recorded observations.
例如:
For example:
-
Java
-
Kotlin
WebClient client = WebClient.builder()
.codecs(configurer -> ... )
.build();
val webClient = WebClient.builder()
.codecs { configurer -> ... }
.build()
一旦构建完毕,一个 WebClient
就是不可变的。但是,你可以像以下代码一样克隆它并构建一个已修改的副本:
Once built, a WebClient
is immutable. However, you can clone it and build a
modified copy as follows:
-
Java
-
Kotlin
WebClient client1 = WebClient.builder()
.filter(filterA).filter(filterB).build();
WebClient client2 = client1.mutate()
.filter(filterC).filter(filterD).build();
// client1 has filterA, filterB
// client2 has filterA, filterB, filterC, filterD
val client1 = WebClient.builder()
.filter(filterA).filter(filterB).build()
val client2 = client1.mutate()
.filter(filterC).filter(filterD).build()
// client1 has filterA, filterB
// client2 has filterA, filterB, filterC, filterD
MaxInMemorySize
码具有limits以便将数据缓存在内存中以避免应用程序内存问题。默认值为 256KB。如果该值不足,你将收到以下错误:
Codecs have limits for buffering data in memory to avoid application memory issues. By default those are set to 256KB. If that’s not enough you’ll get the following error:
org.springframework.core.io.buffer.DataBufferLimitException: Exceeded limit on max bytes to buffer
如需更改默认编解码器的限制,请使用以下方法:
To change the limit for default codecs, use the following:
-
Java
-
Kotlin
WebClient webClient = WebClient.builder()
.codecs(configurer -> configurer.defaultCodecs().maxInMemorySize(2 * 1024 * 1024))
.build();
val webClient = WebClient.builder()
.codecs { configurer -> configurer.defaultCodecs().maxInMemorySize(2 * 1024 * 1024) }
.build()
Reactor Netty
若要自定义 Reactor Netty 设置,请提供一个预先配置的 HttpClient
:
To customize Reactor Netty settings, provide a pre-configured HttpClient
:
-
Java
-
Kotlin
HttpClient httpClient = HttpClient.create().secure(sslSpec -> ...);
WebClient webClient = WebClient.builder()
.clientConnector(new ReactorClientHttpConnector(httpClient))
.build();
val httpClient = HttpClient.create().secure { ... }
val webClient = WebClient.builder()
.clientConnector(ReactorClientHttpConnector(httpClient))
.build()
Resources
默认情况下,HttpClient
参与 reactor.netty.http.HttpResources
中的全局 Reactor Netty 资源,包括事件循环线程和连接池。这是推荐模式,因为固定的共享资源是事件循环并发的首选。在这种模式下,全球资源在进程退出之前保持活动状态。
By default, HttpClient
participates in the global Reactor Netty resources held in
reactor.netty.http.HttpResources
, including event loop threads and a connection pool.
This is the recommended mode, since fixed, shared resources are preferred for event loop
concurrency. In this mode global resources remain active until the process exits.
如果服务器已随进程计时,通常不需要明确关闭。但是,如果服务器可以在进程中启动或停止(例如,作为一个 WAR 部署的 Spring MVC 应用程序),你可以声明一个带有 globalResources=true
(默认)type 的 Spring 管理 bean,以确保在关闭 Spring ApplicationContext
时关闭 Reactor Netty 全局资源,如下例所示:
If the server is timed with the process, there is typically no need for an explicit
shutdown. However, if the server can start or stop in-process (for example, a Spring MVC
application deployed as a WAR), you can declare a Spring-managed bean of type
ReactorResourceFactory
with globalResources=true
(the default) to ensure that the Reactor
Netty global resources are shut down when the Spring ApplicationContext
is closed,
as the following example shows:
-
Java
-
Kotlin
@Bean
public ReactorResourceFactory reactorResourceFactory() {
return new ReactorResourceFactory();
}
@Bean
fun reactorResourceFactory() = ReactorResourceFactory()
你也可以选择不参与全局 Reactor Netty 资源。但是,在这种模式下,确保所有 Reactor Netty 客户端和服务器实例使用共享资源的责任在于你,如下例所示:
You can also choose not to participate in the global Reactor Netty resources. However, in this mode, the burden is on you to ensure that all Reactor Netty client and server instances use shared resources, as the following example shows:
- Java
-
@Bean public ReactorResourceFactory resourceFactory() { ReactorResourceFactory factory = new ReactorResourceFactory(); factory.setUseGlobalResources(false); (1) return factory; } @Bean public WebClient webClient() { Function<HttpClient, HttpClient> mapper = client -> { // Further customizations... }; ClientHttpConnector connector = new ReactorClientHttpConnector(resourceFactory(), mapper); (2) return WebClient.builder().clientConnector(connector).build(); (3) }
1 | Create resources independent of global ones. |
2 | Use the ReactorClientHttpConnector constructor with resource factory. |
3 | Plug the connector into the WebClient.Builder .
|
4 | Create resources independent of global ones. |
5 | Use the ReactorClientHttpConnector constructor with resource factory. |
6 | Plug the connector into the WebClient.Builder . |
Timeouts
配置连接超时:
To configure a connection timeout:
-
Java
-
Kotlin
import io.netty.channel.ChannelOption;
HttpClient httpClient = HttpClient.create()
.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 10000);
WebClient webClient = WebClient.builder()
.clientConnector(new ReactorClientHttpConnector(httpClient))
.build();
import io.netty.channel.ChannelOption
val httpClient = HttpClient.create()
.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 10000);
val webClient = WebClient.builder()
.clientConnector(ReactorClientHttpConnector(httpClient))
.build();
配置读超时或写超时:
To configure a read or write timeout:
-
Java
-
Kotlin
import io.netty.handler.timeout.ReadTimeoutHandler;
import io.netty.handler.timeout.WriteTimeoutHandler;
HttpClient httpClient = HttpClient.create()
.doOnConnected(conn -> conn
.addHandlerLast(new ReadTimeoutHandler(10))
.addHandlerLast(new WriteTimeoutHandler(10)));
// Create WebClient...
import io.netty.handler.timeout.ReadTimeoutHandler
import io.netty.handler.timeout.WriteTimeoutHandler
val httpClient = HttpClient.create()
.doOnConnected { conn -> conn
.addHandlerLast(ReadTimeoutHandler(10))
.addHandlerLast(WriteTimeoutHandler(10))
}
// Create WebClient...
配置针对所有请求的响应超时:
To configure a response timeout for all requests:
-
Java
-
Kotlin
HttpClient httpClient = HttpClient.create()
.responseTimeout(Duration.ofSeconds(2));
// Create WebClient...
val httpClient = HttpClient.create()
.responseTimeout(Duration.ofSeconds(2));
// Create WebClient...
配置针对特定请求的响应超时:
To configure a response timeout for a specific request:
-
Java
-
Kotlin
WebClient.create().get()
.uri("https://example.org/path")
.httpRequest(httpRequest -> {
HttpClientRequest reactorRequest = httpRequest.getNativeRequest();
reactorRequest.responseTimeout(Duration.ofSeconds(2));
})
.retrieve()
.bodyToMono(String.class);
WebClient.create().get()
.uri("https://example.org/path")
.httpRequest { httpRequest: ClientHttpRequest ->
val reactorRequest = httpRequest.getNativeRequest<HttpClientRequest>()
reactorRequest.responseTimeout(Duration.ofSeconds(2))
}
.retrieve()
.bodyToMono(String::class.java)
JDK HttpClient
以下示例显示如何自定义 JDK HttpClient
:
The following example shows how to customize the JDK HttpClient
:
-
Java
-
Kotlin
HttpClient httpClient = HttpClient.newBuilder()
.followRedirects(Redirect.NORMAL)
.connectTimeout(Duration.ofSeconds(20))
.build();
ClientHttpConnector connector =
new JdkClientHttpConnector(httpClient, new DefaultDataBufferFactory());
WebClient webClient = WebClient.builder().clientConnector(connector).build();
val httpClient = HttpClient.newBuilder()
.followRedirects(Redirect.NORMAL)
.connectTimeout(Duration.ofSeconds(20))
.build()
val connector = JdkClientHttpConnector(httpClient, DefaultDataBufferFactory())
val webClient = WebClient.builder().clientConnector(connector).build()
Jetty
以下示例演示了如何自定义 Jetty HttpClient
设置:
The following example shows how to customize Jetty HttpClient
settings:
-
Java
-
Kotlin
HttpClient httpClient = new HttpClient();
httpClient.setCookieStore(...);
WebClient webClient = WebClient.builder()
.clientConnector(new JettyClientHttpConnector(httpClient))
.build();
val httpClient = HttpClient()
httpClient.cookieStore = ...
val webClient = WebClient.builder()
.clientConnector(JettyClientHttpConnector(httpClient))
.build();
默认情况下,HttpClient
创建自己的资源(Executor
、ByteBufferPool
、Scheduler
),它将在进程退出或调用 stop()
之前保持活动状态。
By default, HttpClient
creates its own resources (Executor
, ByteBufferPool
, Scheduler
),
which remain active until the process exits or stop()
is called.
您可以在 Jetty 客户端(和服务器)的多个实例之间共享资源,并确保在关闭 Spring ApplicationContext
时关闭资源,方法是声明一个类型为 JettyResourceFactory
的 Spring 管理 Bean,如下例所示:
You can share resources between multiple instances of the Jetty client (and server) and
ensure that the resources are shut down when the Spring ApplicationContext
is closed by
declaring a Spring-managed bean of type JettyResourceFactory
, as the following example
shows:
- Java
-
@Bean public JettyResourceFactory resourceFactory() { return new JettyResourceFactory(); } @Bean public WebClient webClient() { HttpClient httpClient = new HttpClient(); // Further customizations... ClientHttpConnector connector = new JettyClientHttpConnector(httpClient, resourceFactory()); 1 return WebClient.builder().clientConnector(connector).build(); 2 }
1 | Use the JettyClientHttpConnector constructor with resource factory. |
2 | Plug the connector into the WebClient.Builder .
|
3 | Use the JettyClientHttpConnector constructor with resource factory. |
4 | Plug the connector into the WebClient.Builder . |
HttpComponents
以下示例演示了如何自定义 Apache HttpComponents HttpClient
设置:
The following example shows how to customize Apache HttpComponents HttpClient
settings:
-
Java
-
Kotlin
HttpAsyncClientBuilder clientBuilder = HttpAsyncClients.custom();
clientBuilder.setDefaultRequestConfig(...);
CloseableHttpAsyncClient client = clientBuilder.build();
ClientHttpConnector connector = new HttpComponentsClientHttpConnector(client);
WebClient webClient = WebClient.builder().clientConnector(connector).build();
val client = HttpAsyncClients.custom().apply {
setDefaultRequestConfig(...)
}.build()
val connector = HttpComponentsClientHttpConnector(client)
val webClient = WebClient.builder().clientConnector(connector).build()