摘要:為此我們可以使用來發送一個比如流,會自動為我們實現管道傳輸數據。因為流的長度不確定,請求將使用即分塊傳輸。方法可以被多次安全的調用,這對于無數據的請求很容易復用配置和。如此在接受響應的回調函數里可以直接得到設置的響應解碼體。
本文主要介紹Vert.x 3.4.x 版本新組件Web Client的使用
Vert.x不久前發布了3.4.0 release版本,該版本在語言支持上新增了Scala和Kotlin的支持,新引入了Web Client和Kafka Client,同時加強了微服務組件的功能,支持多種集群管理器供開發者選擇(公司一位同事是vertx-zookeeper集群管理器的開發者),除了這些還有些些微的改動,比如Auth/Security方面的增強,RxJava的支持增強等等,更多的請進入傳送門。
本文不具體對每個新特性做分析,只針對Web Client做介紹,簡單了解下3.4.x版本的Web Client和3.3.x版本的Http Client的差異。
可以明確的是Web Client是Http Client的升級版,他繼承了Http Client的功能特性比如配置,Http/2的支持,pipelining等,同時又提供了一些高級特性,比如表單提交、錯誤處理、30X跳轉等。如果你不需要細粒度的處理http請求/響應,建議你使用Web Client,它已經為你封裝了好了很簡單的方法供你調用,很多API也都來自HttpClient。
使用Web Client前,你需要引入依賴
io.vertx vertx-web-client 3.4.1
創建一個默認的WebClient:
WebClient client = WebClient.create(vertx);
創建一個可配置的WebClient:
WebClientOptions options = new WebClientOptions(); options.setDefaultHost("wonapi.maxleap.cn"); WebClient webClient = WebClient.create(vertx,options);
WebClientOption的配置項全部繼承了HttpClientOption,你可以配置其中任意選項。如果你的應用中已經使用了HttpClient并且配置了Option,你可以復用它:
WebClient client = WebClient.wrap(httpClient);
構建一個無body數據的簡單請求:
HttpRequestrequest = client.request(HttpMethod.GET,"/1.0/orders"); request.send(asyncResult -> { if (asyncResult.succeeded()) { HttpResponse response = asyncResult.result(); System.out.println("status code:"+response.statusCode()); } else { System.err.println("error:"+asyncResult.cause().getMessage()); } });
這適用于GET/OPTIONS/HEAD方式的請求,你可以設置request的query參數,比如
通過request.addQueryParam("param1", "param1_value");來添加query參數,也可以通過request.setQueryParam("param2", "another_param2_value");來覆蓋query參數,你甚至可以通過request.uri("/1.0/orders?param1=param1_value2¶m2=param2_value")來放棄現有的query參數重新設置。
構建一個有body數據的請求:
Buffer buffer = Buffer.buffer("{"a":1}"); HttpRequestrequest = client.request(HttpMethod.POST,"/1.0/orders"); httpRequest.sendBuffer(buffer,asyncResult -> { if (asyncResult.succeeded()) { HttpResponse response = asyncResult.result(); System.out.println("status code:"+response.statusCode()); } else { System.err.println("error:"+asyncResult.cause().getMessage()); } });
上面send方法來發送無body數據的請求,而通過sendXXX方法可以發送一個帶body數據的請求。
sendBuffer 用來發送一個buffer緩沖區數據,這個很有用,但通常我們不希望將內容全部加載到內存里,因為它可能很大,或者我們想處理很多并發請求,并且希望對每個請求使用最小值。
為此我們可以使用sendStream來發送一個ReadStream
fs.open("content.txt", new OpenOptions(), fileRes -> { if (fileRes.succeeded()) { ReadStreamfileStream = fileRes.result(); String fileLen = "1024"; // Send the file to the server using POST client .post(80, "api.maxleap.cn", "/2.0/files") .putHeader("content-length", fileLen) .sendStream(fileStream, ar -> { if (ar.succeeded()) { // Ok } }); } });
上面就是發送一個本地文件content.txt到服務器,通過流傳輸的方式,因為知道文件大小所以沒有使用chunked分塊傳輸。
sendJsonObject 用來發送一個json格式數據,使用它WebClient為自動為你設置Content-Type為application/json。比如:
request.sendJsonObject(new JsonObject().put("name","Jack").put("age",18));
sendJson 用來發送一個POJO,本質上是通過Json.encode來將對象轉化為json字符串(通過Jackson實現)。比如:
request.sendJson(new User("jack",18));
sendForm 用來發送表單數據,使用它WebClient會自動為你設置Content-Type為application/x-www-form-urlencoded。你也可以設置Content-Type為multipart/form-data,但當前版本(目前3.4.1)不支持表單文件上傳,表單文件上傳將會在后續的API版本中支持。比如:
MultiMap form = MultiMap.caseInsensitiveMultiMap(); form.set("name","jack"); form.set("age","18"); client .post(80, "api.maxleap.cn", "/2.0/users") .putHeader("content-type", "multipart/form-data") .sendStream(fileStream, ar -> { if (ar.succeeded()) { // Ok } });
跟HttpClient的API類似,你可以通過request.putHeader("header1":"value1")來添加一條頭信息,也可以通過MultiMap headers = request.headers();來獲取頭信息并操作它(add,addAll,set,setAll,remove等操作)。
send方法可以被多次安全的調用,這對于無body數據的請求很容易復用配置和HttpRequest。同時你可以在request的基礎上修改請求,比如我要復用之前使用過的request,同時修改下頭信息,那么我們只需要調用之前的request對象的putHeader方法即可得到我們想要的新的request。
通過調用request.timeout(10000)你可以為請求設置數據讀取超時時間,如果請求在超時期限內任未返回任何數據,會將異常java.util.concurrent.TimeoutException傳遞給響應處理程序。
send方法接受一個回調函數,用來處理請求發送后異步接受響應結果,需要注意的是默認接受到的響應數據會全部緩沖存放在內存里(通過request.as(BodyCodec.buffer())設置),如果數據很大,建議你通過request.as(BodyCodec.pipe(writeStream))將響應傳遞給寫入流中,你也可以通過BodyCodec實現你想要的響應體解碼,比如request.as(BodyCodec.jsonObject())將響應解析為JsonObject,request.as(BodyCodec.json(User.class))將響應解析為POJO,如果你不關注響應數據,你可以通過request.as(BodyCodec.none())來忽略響應體。如此在接受響應的回調函數里可以直接得到request.as()設置的響應解碼體。比如:
client .get(80, "api.maxleap.cn", "/2.0/users") .as(BodyCodec.json(User.class)) .send(ar -> { if (ar.succeeded()) { HttpResponseresponse = ar.result(); User user = response.body(); System.out.println("Received response with status code" + response.statusCode() + " with body " + user.toString()); } else { System.out.println("Something went wrong " + ar.cause().getMessage()); } });
默認情況下,你可以在處理響應時直接使用bodyAsXXX()來解析成想要的響應體,這只針對默認的request.as(BodyCodec.buffer())有效。
vertx 3.3.x的HttpClient是不支持30X重定向的,需要自己實現跳轉邏輯,在3.4.x中WebClient默認為我們實現了自動重定向,我們可以在WebClientOption中配置30X重定向的配置:
WebClientOptions options = new WebClientOptions(); options .setFollowRedirects(true)//設置遵循重定向 .setMaxRedirects(5);//最大重定向次數 WebClient webClient = WebClient.create(vertx,options);
Vert.x web client 可以跟HttpClient相同的方式使用https:
client .get(443, "api.maxleap.cn", "/2.0/users") .ssl(true) .send(ar -> { if (ar.succeeded()) { // OK } });
或者直接通過決定路徑發起https請求:
client .getAbs("https://api.maxleap.cn/2.0/users") .send(ar -> { if (ar.succeeded()) { // OK } });
Vert.x RxJava是一個非常受歡迎的響應式編程擴展程序包,3.4.X版本增強了對RxJava的支持,原本返回Observable的API全部更改為返回rx.Single,使其語義更加清晰,結合Vert.x Web Client,將會是一個非常強大的組合。
io.vertx.rxjava.core.Vertx rxVertx = io.vertx.rxjava.core.Vertx.vertx(); io.vertx.rxjava.ext.web.client.WebClient rxWebClient = io.vertx.rxjava.ext.web.client.WebClient.create(rxVertx); rxWebClient.get(80,"api.maxleap.cn","/2.0/users") .putHeader("header1","header1-value") .addQueryParam("query1","query1-value") .as(io.vertx.rxjava.ext.web.codec.BodyCodec.jsonObject()) .rxSend() .subscribe(response -> {}, Throwable::printStackTrace);
rxSend方法返回一個Single
作者信息
原文系力譜云旗下技術團隊_云服務研發成員:David Young
首發鏈接:https://blog.maxleap.cn/archi...
相關文章
Maxleap Vert.x應用實踐總結
次時代Java編程(一):續 vertx-sync實踐
使用Vert.x構建Web服務器和消息系統
歡迎關注微信公眾號
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/66998.html
摘要:主要是避免引入太多的復雜性,并且出于靈活部署的需要。以應用為例,由于實際上是在上執行,若它被阻塞,即導致后續請求全部無法得到處理。因此,最合適的做法就是對于簡單業務,采用異步庫。本系列其他文章入坑須知入坑須知入坑須知 最開始覺得這個系列也就最多3篇了不起了(因為事不過三嘛),沒曾想居然迎來了第四篇! Kotlin 由于最近決定投身到區塊鏈的學習當中的緣故,出于更好的理解它的基本概念,自...
摘要:本文章是藍圖系列的第二篇教程。這就是請求回應模式。好多屬性我們一個一個地解釋一個序列,作為的地址任務的編號任務的類型任務攜帶的數據,以類型表示任務優先級,以枚舉類型表示。默認優先級為正常任務的延遲時間,默認是任務狀態,以枚舉類型表示。 本文章是 Vert.x 藍圖系列 的第二篇教程。全系列: Vert.x Blueprint 系列教程(一) | 待辦事項服務開發教程 Vert.x B...
摘要:本文章是藍圖系列的第一篇教程。是事件驅動的,同時也是非阻塞的。是一組負責分發和處理事件的線程。注意,我們絕對不能去阻塞線程,否則事件的處理過程會被阻塞,我們的應用就失去了響應能力。每個負責處理請求并且寫入回應結果。 本文章是 Vert.x 藍圖系列 的第一篇教程。全系列: Vert.x Blueprint 系列教程(一) | 待辦事項服務開發教程 Vert.x Blueprint 系...
摘要:定時器例子之前通過調用定時器,需要傳一個回調,然后所有的代碼邏輯都包在里面。這里定時器會阻塞在這一行,直到一秒后才會執行下面的一行。 之前介紹過quasar,如果你希望在vert.x項目里使用coroutine的話,建議使用vertx-sync。本篇將介紹vertx-sync。 showImg(/img/bVzIsu); 本來打算另起一篇,寫其他方面的東西,但是最近比較忙,就先寫一篇實...
摘要:本教程是藍圖系列的第三篇教程,對應的版本為。提供了一個服務發現模塊用于發布和獲取服務記錄。前端此微服務的前端部分,目前已整合至組件中。監視儀表板用于監視微服務系統的狀態以及日志統計數據的查看。而服務則負責發布其它服務如服務或消息源并且部署。 本文章是 Vert.x 藍圖系列 的第三篇教程。全系列: Vert.x Blueprint 系列教程(一) | 待辦事項服務開發教程 Vert....
閱讀 2762·2021-11-22 13:54
閱讀 2697·2021-10-14 09:42
閱讀 4038·2021-09-28 09:47
閱讀 2171·2021-09-03 10:28
閱讀 1215·2021-07-26 23:38
閱讀 2566·2019-08-30 15:54
閱讀 2645·2019-08-29 16:35
閱讀 1436·2019-08-29 15:42