本文是精講響應式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<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響應結果,和我們通過程式列印出的響應結果資料內容一致。程式控制臺截圖如下:
接收響應結果的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條記錄):
所以我們需要通過bodyToFlux方法將請求結果轉為Flux<PostDTO>
,通過flux.collectList().block();
接收響應資料為 List<PostDTO>
集合。Flux英文含義:流動的,用於接收集合元素響應結果。
@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());
}
控制檯列印結果如下:
二、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);
}
控制檯列印輸出結果如下:
三、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報文資訊詳情控制檯列印結果
四、佔位符傳參
非佔位符傳參,寫死的引數方式不靈活
.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)
歡迎關注我的部落格,裡面有很多精品合集
- 本文轉載註明出處(必須帶連線,不能只轉文字):字母哥部落格。
覺得對您有幫助的話,幫我點贊、分享!您的支援是我不竭的創作動力! 。另外,筆者最近一段時間輸出瞭如下的精品內容,期待您的關注。