从 Spring 5 开始,Spring 中全面引入了 Reactive 响应式编程。而 WebClient 则是 Spring WebFlux 模块提供的一个非阻塞的基于响应式编程的进行 Http 请求的客户端工具。
由于 WebClient 的请求模式属于异步非阻塞,能够以少量固定的线程处理高并发的 HTTP 请求。因此,从 Spring 5 开始,HTTP 服务之间的通信我们就可以考虑使用 WebClient 来取代之前的 RestTemplate。
下面记录 WebClient 的基本使用方法,并记录如何通过 WebClient 发送 GET 和 POST 请求。
1.添加依赖
要使用 WebClient,首先需要在 Maven 项目中添加 Spring WebFlux 依赖:
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-webflux</artifactId></dependency>
对于 Gradle 项目:
implementation 'org.springframework.boot:spring-boot-starter-webflux'
2.创建 WebClient 实例
可以通过多种方式创建 WebClient 实例:
方式一:全局 WebClient Bean(推荐)
在 Spring 项目中,通常会通过定义一个 WebClient.Builder Bean,并在需要的地方注入。
@ConfigurationpublicclassWebClientConfig{@BeanpublicWebClient.BuilderwebClientBuilder(){returnWebClient.builder();}}
然后在服务中使用:
@ServicepublicclassMyService{privatefinalWebClient webClient;publicMyService(WebClient.Builder webClientBuilder){this.webClient = webClientBuilder.baseUrl("https://example.com").build();}publicStringgetData(){return webClient.get().uri("/api/data").retrieve().bodyToMono(String.class).block();// 这里使用 block() 表示阻塞操作}}
方式二:使用静态创建方法
可以直接使用 WebClient.create() 创建客户端实例:
WebClient webClient =WebClient.create("https://example.com");
3.发送请求
3.1 发送 GET 请求
publicStringgetData(){WebClient webClient =WebClient.create("https://jsonplaceholder.typicode.com");String response = webClient.get().uri("/posts/1").retrieve().bodyToMono(String.class).block();return response;}
- retrieve():用于发出请求并获取响应。
- bodyToMono(String.class):将响应体转换为Mono,Mono 表示一个异步的单值序列。
- block():阻塞当前线程,直到请求完成并返回结果。
3.2 发送 POST 请求
下面是一个发送 POST 请求并传递 JSON 数据的例子:
publicStringpostData(){WebClient webClient =WebClient.create("https://jsonplaceholder.typicode.com");String response = webClient.post().uri("/posts").header(HttpHeaders.CONTENT_TYPE,MediaType.APPLICATION_JSON_VALUE).bodyValue("{ \"title\": \"foo\", \"body\": \"bar\", \"userId\": 1 }").retrieve().bodyToMono(String.class).block();return response;}
- bodyValue():设置请求体的数据,可以传递字符串、对象、或者其他序列化格式。
- block():同步等待请求完成。
3.3 异步请求
如果不想阻塞线程,可以使用 WebClient 的异步处理功能。例如,使用 subscribe() 来处理异步请求:
publicvoidgetDataAsync(){WebClient webClient =WebClient.create("https://jsonplaceholder.typicode.com");
webClient.get().uri("/posts/1").retrieve().bodyToMono(String.class).subscribe(response ->{System.out.println("异步响应: "+ response);});}
这里使用了 subscribe() 方法,它接受一个 Consumer 回调函数,当响应到达时触发这个回调函数。
4. 处理错误响应
通过 WebClient,可以使用 onStatus() 来处理特定的 HTTP 响应状态码:
publicStringgetDataWithErrorHandling(){WebClient webClient =WebClient.create("https://jsonplaceholder.typicode.com");return webClient.get().uri("/posts/invalid").retrieve().onStatus(HttpStatus::is4xxClientError, response ->{return response.bodyToMono(String.class).flatMap(errorBody ->Mono.error(newRuntimeException("4xx 错误: "+ errorBody)));}).onStatus(HttpStatus::is5xxServerError, response ->{return response.bodyToMono(String.class).flatMap(errorBody ->Mono.error(newRuntimeException("5xx 错误: "+ errorBody)));}).bodyToMono(String.class).block();}
5. 超时配置
可以通过自定义 WebClient 的 HttpClient 来设置超时时间:
importreactor.netty.http.client.HttpClient;importjava.time.Duration;HttpClient httpClient =HttpClient.create().responseTimeout(Duration.ofSeconds(5));// 设置响应超时WebClient webClient =WebClient.builder().clientConnector(newReactorClientHttpConnector(httpClient)).build();
6. 文件上传
通过 WebClient 实现文件上传,可以使用 multipart/form-data 来传递文件:
importorg.springframework.http.MediaType;importorg.springframework.core.io.FileSystemResource;importorg.springframework.core.io.Resource;publicStringuploadFile(){WebClient webClient =WebClient.create("https://example.com");Resource file =newFileSystemResource("/path/to/file.txt");return webClient.post().uri("/upload").contentType(MediaType.MULTIPART_FORM_DATA).bodyValue(file).retrieve().bodyToMono(String.class).block();}
总结:
- 同步调用: 可以使用 .block() 让 WebClient 的调用同步阻塞,方便传统开发者的过渡。
- 异步调用: 通过 Mono 和Flux 支持异步和响应式的编程模型,非常适合处理大量并发请求。
- 丰富的错误处理: 可以通过 onStatus() 针对不同的状态码进行错误处理。
- 灵活性强: 可以自定义超时、拦截器、连接池等,适应各种复杂场景。
版权归原作者 阿噜噜同学 所有, 如有侵权,请联系我们删除。