参考:
多年来,Spring 框架的 RestTemplate 一直是客户端 HTTP 访问的首选解决方案,它提供同步、阻塞 API 来以简单的方式处理 HTTP 请求。
然而,随着对非阻塞、反应式编程以更少的资源处理并发的需求不断增加,特别是在微服务架构中,RestTemplate 已经显示出其局限性。从 Spring Framework 5 开始,RestTemplate 已被标记为已弃用,Spring 团队推荐 WebClient 作为其继任者。
RestTemplate 与 WebClient 区别:
<!--WebClient-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
@Test
void webclientCreate(){
//WebClient webClient = WebClient.builder().baseUrl(BASE_URI).build();
WebClient webClient = WebClient.create(BASE_URI);
//普通请求
Mono<String> mono = webClient
.get() //get请求
.uri(BASE_URI + "/test/get01") //WebClient.create()不带BASE_URI时就得写上请求头
.retrieve() //获取响应体
.bodyToMono(String.class); //格式化响应数据
//携带请求参数——拼接请求地址栏
Mono<String> mono01 = webClient
.get()
.uri(uriBuilder -> uriBuilder
.path("/test/get02")
.queryParam("pageSize",10)
.queryParam("pageNum",1)
.build())
.retrieve()
.bodyToMono(String.class);
//携带请求参数——放到body中
User user = User.builder().id("0000").password("0000").build();
Mono<User> mono02 = webClient
.post()
.uri(uriBuilder -> uriBuilder.path("/test/post01").build())
.contentType(MediaType.APPLICATION_JSON)
.body(Mono.just(user),User.class)
// .header()
.retrieve()
.bodyToMono(User.class);
}
log.info("{}",mono.block());
mono.subscribe(result -> System.out.println(result));//subscribe()方法用于订阅结果,一旦可用就会对其进行处理
RestTemplate 的错误处理通过ErrorHandler
接口进行,这需要单独的代码块,而 WebClient 允许直接在操作链中处理特定的 HTTP 状态,从而提供更具可读性和可维护性的方法
WebClient webClient = WebClient.create();
webClient.get()
.uri( "http://example.com/some-error-endpoint" )
.retrieve()
.onStatus(HttpStatus::isError, response -> {
// 处理错误状态码
return Mono.error ( new CustomException ( "发生自定义错误。" ));
})
.bodyToMono(String.class);
WebClient 还支持以数据流的形式检索响应主体,这在处理您不想一次将其全部保存在内存中的大量数据时特别有用。
WebClient webClient = WebClient.create();
webClient.get()
.uri( "http://example.com/stream" )
.accept(MediaType.TEXT_EVENT_STREAM) // 用于服务器发送事件 (SSE)
.retrieve()
.bodyToFlux(String.class) //将响应正文转换为 Flux
.subscribe(data -> System.out.println( "Received: " + data));
在此场景中,bodyToFlux用于将响应正文转换为Flux,表示数据流。然后,该subscribe方法用于在每条数据到达时对其进行处理。这与 RestTemplate 形成鲜明对比,后者要求在处理之前将整个响应主体加载到内存中,无论大小如何。
WebClient webClient = WebClient.builder().baseUrl( "http://example.com" ).build();
Mono<String> response = webClient.get()
.uri( "/retry-endpoint" )
.retrieve()
.bodyToMono(String.class)
.retryWhen(Retry.backoff( 3 , Duration.ofSeconds( 1 )) //重试次数和退避配置
.maxBackoff(Duration.ofSeconds( 10 ))) // 最大退避时间
.onErrorResume(e -> Mono.just( "Fallback response" )); // 如果重试都失败则回退
response.subscribe(result -> System.out.println(result));
在此示例中,该retryWhen方法用于定义重试策略,指定重试次数和退避配置。如果所有重试都失败,onErrorResume
则提供后备机制。
等等…