WebClient.Builder
是Spring Framework中用于构建和配置WebClient
实例的工具。WebClient
是一种用于进行HTTP请求的非阻塞式客户端,它提供了一种简洁而灵活的方式来进行服务之间的通信。
下面是WebClient.Builder
的一些常见使用场景和作用:
-
创建和配置
WebClient
实例: 主要作用是用于创建和配置WebClient
实例。通过WebClient.Builder
,可以定义WebClient
实例的基本属性,例如设置基本URL、设置连接超时、配置请求和响应的编解码器等。 -
定义全局配置: 通常情况下,我们希望在应用程序中共享一些公共的
WebClient
配置。可以使用WebClient.Builder
来定义全局的配置,然后在需要创建WebClient
实例时使用该配置。 -
灵活地定制
WebClient
实例:WebClient.Builder
提供了丰富的配置选项,可以根据具体需求来定制WebClient
实例。例如,可以设置请求和响应的编解码器、添加过滤器(filter)来修改请求或响应、设置连接器(connector)来配置底层的HTTP客户端等。 -
支持链式调用和流式配置: 使用
WebClient.Builder
可以进行链式调用,可以很方便地对多个配置进行组合和设置。这种流式配置的方式使得代码更加清晰和易于理解。 -
替代传统的RestTemplate: 在Spring框架中,
RestTemplate
是一个常用的HTTP客户端,用于发送HTTP请求。然而,WebClient
提供了更为现代化和灵活的替代方案。通过WebClient.Builder
,可以创建出与RestTemplate
类似的HTTP客户端,并且具有更好的性能和更多的扩展能力。
总的来说,WebClient.Builder
是用于创建和配置WebClient
实例的工具,它提供了丰富的配置选项,可以根据具体需求来定制和管理WebClient
实例,是实现服务之间通信的重要工具之一。
1、启动类相关基础配置(Nocas或Eureka)
/**
* @author Lucas
* date 2024/3/7 11:22
* description 项目启动类
*/
@SpringBootApplication
@EnableDiscoveryClient
public class TestServiceApplication {
@Bean
@LoadBalanced
public WebClient.Builder webClientBuilder(){
return WebClient.builder();
}
public static void main(String[] args) {
SpringApplication.run(TestServiceApplication.class, args);
}
}
2、服务接口调用通用配置
/**
* @author Lucas
* date 2024/3/7 11:22
* description 通用配置类
*/
@Component
public class WebClientConfig {
private final ConnectionProvider provider = ConnectionProvider.create("global-webclient-config", 80000);
private final Duration requestTimeout = Duration.ofSeconds(10L);
private final int maxInMemBufferSize = 1048576;
public WebClientConfig() {
}
public WebClient createDefaultWebClient(WebClient.Builder builder) {
HttpClient client = HttpClient.create(this.provider).responseTimeout(this.requestTimeout);
return builder.clientConnector(new ReactorClientHttpConnector(client)).exchangeStrategies(ExchangeStrategies.builder().codecs((configurer) -> {
configurer.defaultCodecs().maxInMemorySize(1048576);
}).build()).build();
}
public WebClient createWebClient(WebClient.Builder builder, Duration vReqTimeout, int vMaxInMemBufferSize) {
HttpClient client = HttpClient.create(this.provider).responseTimeout(vReqTimeout);
return builder.clientConnector(new ReactorClientHttpConnector(client)).exchangeStrategies(ExchangeStrategies.builder().codecs((configurer) -> {
configurer.defaultCodecs().maxInMemorySize(vMaxInMemBufferSize);
}).build()).build();
}
public ConnectionProvider getProvider() {
return this.provider;
}
public Duration getRequestTimeout() {
return this.requestTimeout;
}
public int getMaxInMemBufferSize() {
Objects.requireNonNull(this);
return 1048576;
}
}
3、服务之间调用实现类
/**
* @author Lucas
* date 2024/3/7 11:22
* description 测试服务调用
*/
@Service
public class TestReactiveRemote {
private static final String URI = "http://test-service/test";
private static final String HEADER_METHOD = "X-HTTP-Method-Override";
private final WebClientConfig webClientConfig;
private final WebClient.Builder builder;
public TestReactiveRemote(WebClientConfig webClientConfig, WebClient.Builder builder) {
this.webClientConfig = webClientConfig;
this.builder = builder;
}
public Mono<R<List<TestVo>>> getTestList(String name) {
return webClientConfig.createDefaultWebClient(builder)
.post()
.uri(URI + "/getTestList" + "?name=" + name)
.headers(httpHeaders -> httpHeaders.add(HEADER_METHOD, "GET"))
.exchangeToMono(response -> {
if (response.statusCode().equals(HttpStatus.OK)) {
return response.bodyToMono(new ParameterizedTypeReference<R<List<TestVo>>>() {});
} else {
return response.createException().flatMap(error -> Mono.error(new Exception(error.getMessage())));
}
})
.timeout(Duration.ofSeconds(10));
}
public Mono<R<String>> createTest(TestDto testDto) {
return webClientConfig.createDefaultWebClient(builder)
.post()
.uri(URI + "/createTest")
.headers(httpHeaders -> httpHeaders.add(HEADER_METHOD, "POST"))
.contentType(MediaType.APPLICATION_JSON)
.body(BodyInserters.fromValue(JSONObject.toJSONString(testDto)))
.exchangeToMono(response -> {
if (response.statusCode().equals(HttpStatus.OK)) {
return response.bodyToMono(new ParameterizedTypeReference<R<String>>() {});
} else {
return response.createException().flatMap(error -> Mono.error(new Exception(error.getMessage())));
}
})
.timeout(Duration.ofSeconds(10));
}
}