WebClient客户端既支持同步异步、阻塞与非阻塞IO,我们先来为大家介绍一下同步阻塞式的编程方式。即:在请求发送之后使用block()方法,阻塞当前线程等待获取响应结果。
创建测试用例,成员变量WebClient,以 "http://jsonplaceholder.typicode.com"为访问服务基础路径,该网站是一个免费提供RESTful API进行接口测试的一个网站。
public class GetTest { //创建webClient private WebClient webClient = WebClient.builder() .baseUrl("http://jsonplaceholder.typicode.com") .build(); @Test public void testMono() { Mono<PostDTO> mono = webClient .get() // 发送GET 请求 .uri("/posts/1") //服务请求路径,基于baseurl .retrieve() // 获取响应体 .bodyToMono(PostDTO.class); //响应数据类型转换 System.out.println(mono.block()); } }
通过浏览器访问 "http://jsonplaceholder.typicode.com/posts/1" 得到JSON响应结果,和我们通过程序打印出的响应结果数据内容一致。程序控制台截图如下:
接收响应结果的java POJO实体对象如下:
import lombok.Data; @Data public class PostDTO { private int userId; private int id; private String title; private String body; }
访问http://jsonplaceholder.typicode.com/posts 可以获得JSON数组方式的请求结果如图(一共100条我截图截取3条记录):
所以我们需要通过bodyToFlux方法将请求结果转为Flux<PostDTO>,通过flux.collectList().block();接收响应数据为 List<PostDTO>集合。Flux英文含义:流动的,用于接收集合元素响应结果。
Flux<PostDTO>
flux.collectList().block();
List<PostDTO>
@Test public void testFlux() { Flux<PostDTO> flux = webClient .get() // 发送GET 请求 .uri("/posts") //服务请求路径,基于baseurl .retrieve() // 获取响应体 .bodyToFlux(PostDTO.class); //响应数据类型转换 List<PostDTO> posts = flux.collectList().block(); assert posts != null; System.out.println("获取posts集合元素数量:" + posts.size()); }
控制台打印结果如下:
与block()阻塞式获取响应结果不同,使用subscribe()异步订阅响应结果,不会阻塞主线程继续向下执行。获取到响应结果之后,由回调函数handleResponse处理响应结果。
@Test public void testSubscribe() throws InterruptedException { Mono<PostDTO> mono = webClient .get() // 发送GET 请求 .uri("/posts/1") //服务请求路径,基于baseurl .retrieve() // 获取响应体 .bodyToMono(PostDTO.class); //响应数据类型转换 //异步非阻塞处理响应结果 mono.subscribe(GetTest::handleResponse); //为了避免测试用例主线程执行完成,导致看不到异步处理结果 Thread.currentThread().sleep(10000); } //响应结果处理回调方法 private static void handleResponse(PostDTO postDTO) { System.out.println("handle response:======================="); System.out.println(postDTO); }
控制台打印输出结果如下:
上文中retrieve()只能获取HTTP报文中的Body,也就是响应体。如果我们想获取HTTP报文中的状态码、headers、cookies等信息,需要使用exchange()方法。
@Test public void testExchange() { Mono<ClientResponse> mono = webClient .get() // 发送GET 请求 .uri("/posts/1") //服务请求路径,基于baseurl .exchange(); System.out.println(mono.block()); // 获取完整的响应对象 ClientResponse response = mono.block(); assert response != null; HttpStatus httpStatus = response.statusCode(); // 获取响应状态 int statusCodeValue = response.rawStatusCode(); // 获取响应状态码 ClientResponse.Headers headers = response.headers(); // 获取响应头 // 获取响应体 Mono<PostDTO> resultMono = response.bodyToMono(PostDTO.class); PostDTO postDTO = resultMono.block(); // 输出结果 System.out.println("响应状态:" + httpStatus); System.out.println("响应状态码值:" + statusCodeValue); System.out.println("HTTP Headers:" + headers.asHttpHeaders()); System.out.println("响应体:" + postDTO); }
HTTP报文信息详情控制台打印结果
非占位符传参,写死的参数方式不灵活
.uri("/posts/1") //服务请求路径,基于baseurl
第一种占位符传参:数字顺序占位符
Mono<String> mono = webClient.uri("/{1}/{2}", "posts", "1")
第二种占位符传参:参数名称占位符
String type = "posts"; int id = 1; Mono<String> mono = webClient.uri("/{type}/{id}", type, id)
第三种通过map传参
Map<String,Object> map = new HashMap<>(); map.put("type", "posts"); map.put("id", 1); Mono<String> mono = webClient .uri("/{type}/{id}", map)
原文链接:https://www.cnblogs.com/zimug/p/13539042.html