block才会执行 mono_精讲响应式WebClient第2篇-GET请求阻塞与非阻塞调用方法详解

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

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

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

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

1.1.使用Mono接收单个对象

创建测试用例,成员变量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 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响应结果,和我们通过程序打印出的响应结果数据内容一致。程序控制台截图如下:

3c47a76a32244fdc30c678fd595e6d6b.png

接收响应结果的java POJO实体对象如下:

import lombok.Data;

@Data

public class PostDTO {

private int userId;

private int id;

private String title;

private String body;

}

1.2.使用Flux接收集合对象

bf7363a871f5a9d4076e45e5f5b1fe41.png

所以我们需要通过bodyToFlux方法将请求结果转为Flux,通过flux.collectList().block();接收响应数据为 List集合。Flux英文含义:流动的,用于接收集合元素响应结果。

@Test

public void testFlux() {

Flux flux = webClient

.get() // 发送GET 请求

.uri("/posts") //服务请求路径,基于baseurl

.retrieve() // 获取响应体

.bodyToFlux(PostDTO.class); //响应数据类型转换

List posts = flux.collectList().block();

assert posts != null;

System.out.println("获取posts集合元素数量:" + posts.size());

}

控制台打印结果如下:

ad1d6d131f7d94147e72ec8d2f95a8d5.png

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

与block()阻塞式获取响应结果不同,使用subscribe()异步订阅响应结果,不会阻塞主线程继续向下执行。获取到响应结果之后,由回调函数handleResponse处理响应结果。

@Test

public void testSubscribe() throws InterruptedException {

Mono 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);

}

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

7e1a7b802e824b38422b1b8e2785cdde.png

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

上文中retrieve()只能获取HTTP报文中的Body,也就是响应体。如果我们想获取HTTP报文中的状态码、headers、cookies等信息,需要使用exchange()方法。

@Test

public void testExchange() {

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

e2a860cff9dd0947810317686a0a3580.png

四、占位符传参

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

.uri("/posts/1") //服务请求路径,基于baseurl

第一种占位符传参:数字顺序占位符

Mono mono = webClient.uri("/{1}/{2}", "posts", "1")

第二种占位符传参:参数名称占位符

String type = "posts";

int id = 1;

Mono mono = webClient.uri("/{type}/{id}", type, id)

第三种通过map传参

Map map = new HashMap<>();

map.put("type", "posts");

map.put("id", 1);

Mono mono = webClient

.uri("/{type}/{id}", map)

喜欢 (3)or分享 (0)


版权声明:本文为weixin_30610943原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。