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: Customized UriBuilderFactory 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.
Kotlin
@Bean
fun resourceFactory() = ReactorResourceFactory().apply {
	isUseGlobalResources = false (1)
}

@Bean
fun webClient(): WebClient {

	val mapper: (HttpClient) -> HttpClient = {
		// Further customizations...
	}

	val connector = ReactorClientHttpConnector(resourceFactory(), mapper) (2)

	return WebClient.builder().clientConnector(connector).build() (3)
}
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 创建自己的资源(ExecutorByteBufferPoolScheduler),它将在进程退出或调用 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.
Kotlin
@Bean
fun resourceFactory() = JettyResourceFactory()

@Bean
fun webClient(): WebClient {

	val httpClient = HttpClient()
	// Further customizations...

	val connector = JettyClientHttpConnector(httpClient, resourceFactory()) (1)

	return WebClient.builder().clientConnector(connector).build() (2)
}
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()