精讲响应式WebClient第2篇-GET请求阻塞与非阻塞调用方法详解

本文是精讲响应式WebClient第2篇,前篇的blog访问地址以下:html

在上一篇文章为你们介绍了响应式IO模型和WebClient的基本用法。本节来继续深刻的为你们介绍:如何使用WebClient做为Http客户端发送GET请求与进行响应结果的接收。vue

1、block()阻塞式获取响应结果

WebClient客户端既支持同步异步、阻塞与非阻塞IO,咱们先来为你们介绍一下同步阻塞式的编程方式。即:在请求发送以后使用block()方法,阻塞当前线程等待获取响应结果。java

1.1.使用Mono接收单个对象

建立测试用例,成员变量WebClient,以 "http://jsonplaceholder.typicode.com" 为访问服务基础路径,该网站是一个免费提供RESTful API进行接口测试的一个网站。web

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());
  }

}
  • get() 方法表示使用HTTP GET method
  • uri() 指定服务接口路径,以baseurl为基础
  • retrieve() 获取响应体,即HTTP body
  • bodyToMono()将响应体转换为一个对象,Mono英文是单声道、单体的意思,用于接收单个对象

经过浏览器访问 "http://jsonplaceholder.typicode.com/posts/1" 获得JSON响应结果,和咱们经过程序打印出的响应结果数据内容一致。程序控制台截图以下:spring

接收响应结果的java POJO实体对象以下:编程

import lombok.Data;

@Data
public class PostDTO {
    private int userId;
    private int id;
    private String title;
    private String body;
}

1.2.使用Flux接收集合对象

访问http://jsonplaceholder.typicode.com/posts 能够得到JSON数组方式的请求结果如图(一共100条我截图截取3条记录):json


因此咱们须要经过bodyToFlux方法将请求结果转为Flux<PostDTO>,经过flux.collectList().block();接收响应数据为 List<PostDTO>集合。Flux英文含义:流动的,用于接收集合元素响应结果。segmentfault

@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());
}

控制台打印结果以下:后端

2、subscribe()非阻塞式获取响应结果

与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);
}

控制台打印输出结果以下:

3、exchange()获取HTTP响应完整内容

上文中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报文信息详情控制台打印结果

4、占位符传参

非占位符传参,写死的参数方式不灵活

.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)

欢迎关注个人博客,里面有不少精品合集

  • 本文转载注明出处(必须带链接,不能只转文字):字母哥博客

以为对您有帮助的话,帮我点赞、分享!您的支持是我不竭的创做动力! 。另外,笔者最近一段时间输出了以下的精品内容,期待您的关注。