本文參考自Vert.x Web Client官方文檔珊拼。套用官網(wǎng)的話(huà)來(lái)說(shuō),
Vert.x Web Client是一個(gè)異步的HTTP和HTTP/2網(wǎng)絡(luò)客戶(hù)端流炕。
相對(duì)來(lái)說(shuō)澎现,這是一個(gè)比較小的框架,而且功能也很直接每辟,做一個(gè)方便好用的HTTP客戶(hù)端剑辫。它具有以下功能:
- Json body 編碼 / 解碼
- request 參數(shù)
- 統(tǒng)一的錯(cuò)誤處理
- 表單提交
需要注意,它和Vertx核心包中的HttpClient
有很多聯(lián)系渠欺。它繼承了HttpClient
妹蔽,提供了更多功能。
引用類(lèi)庫(kù)
要使用這個(gè)類(lèi)庫(kù)很簡(jiǎn)單挠将。如果使用Maven胳岂,添加下面的依賴(lài)。
<dependency>
<groupId>io.vertx</groupId>
<artifactId>vertx-web-client</artifactId>
<version>3.4.2</version>
</dependency>
如果使用Gradle舔稀,添加下面的依賴(lài)乳丰。
dependencies {
compile 'io.vertx:vertx-web-client:3.4.2'
}
創(chuàng)建客戶(hù)端
創(chuàng)建客戶(hù)端稍微有點(diǎn)不一樣。
WebClient client = WebClient.create(vertx);
如果要添加配置參數(shù)内贮,可以這樣做产园。
WebClientOptions options = new WebClientOptions()
.setUserAgent("My-App/1.2.3");
options.setKeepAlive(false);
WebClient client = WebClient.create(vertx, options);
如果已經(jīng)有了HttpClient
,可以重用它夜郁。
WebClient client = WebClient.wrap(httpClient);
發(fā)起請(qǐng)求
無(wú)請(qǐng)求體的請(qǐng)求
這是最簡(jiǎn)單的情況什燕,一般的GET、HEAD等請(qǐng)求都輸這種方式拂酣。
webClient.get("www.baidu.com", "/")
.send(ar -> {
if (ar.succeeded()) {
HttpResponse<Buffer> response = ar.result();
System.out.println(response.body());
} else {
System.out.println(ar.cause());
}
});
如果要攜帶查詢(xún)參數(shù)秋冰,可以采用流式API。
client
.get(8080, "myserver.mycompany.com", "/some-uri")
.addQueryParam("param", "param_value")
.send(ar -> {});
也可以直接在URL中設(shè)置查詢(xún)參數(shù)婶熬。
HttpRequest<Buffer> request = client.get(8080, "myserver.mycompany.com", "/some-uri");
// 添加參數(shù)1
request.addQueryParam("param1", "param1_value");
// 用URL覆蓋參數(shù)
request.uri("/some-uri?param1=param1_value¶m2=param2_value");
添加請(qǐng)求體
假如使用POST方式傳遞參數(shù)剑勾,或者上傳圖片等,就需要帶有請(qǐng)求體的請(qǐng)求了赵颅。這種情況下虽另,只需要額外使用sendXXX
等方法添加要傳遞的請(qǐng)求體即可。
webClient.post("httpbin.org", "/post")
.sendBuffer(Buffer.buffer("name=yitian&age=25"), ar -> {
if (ar.succeeded()) {
HttpResponse<Buffer> response = ar.result();
System.out.println(response.body());
}
});
如果要發(fā)送的信息比較大饺谬,可以使用sendStream
方法捂刺,使用流來(lái)傳輸數(shù)據(jù)。
client
.post(8080, "myserver.mycompany.com", "/some-uri")
.sendStream(stream, resp -> {});
Json請(qǐng)求體
有時(shí)候可能需要發(fā)送Json數(shù)據(jù)募寨,這時(shí)候可以使用sendJsonObject
方法族展。
client
.post(8080, "myserver.mycompany.com", "/some-uri")
.sendJsonObject(new JsonObject()
.put("firstName", "Dale")
.put("lastName", "Cooper"), ar -> {
if (ar.succeeded()) {
// Ok
}
});
發(fā)送表單
發(fā)送表單使用sendForm
方法。
MultiMap multiMap = MultiMap.caseInsensitiveMultiMap();
multiMap.add("name", "yitian");
multiMap.add("age", "25");
webClient.post("httpbin.org", "/post")
.sendForm(multiMap, ar -> {
if (ar.succeeded()) {
HttpResponse<Buffer> response = ar.result();
System.out.println(response.body());
}
});
默認(rèn)表單使用application/x-www-form-urlencoded
類(lèi)型的Content Type發(fā)送拔鹰,也可以修改成multipart/form-data
類(lèi)型仪缸。
client
.post(8080, "myserver.mycompany.com", "/some-uri")
.putHeader("content-type", "multipart/form-data")
.sendForm(form, ar -> {
if (ar.succeeded()) {
// Ok
}
});
目前上傳文件還不支持,將會(huì)在以后的版本中支持上傳文件列肢。
修改請(qǐng)求頭
可以添加和修改要發(fā)送的請(qǐng)求頭恰画。
HttpRequest<Buffer> request = client.get(8080, "myserver.mycompany.com", "/some-uri");
MultiMap headers = request.headers();
headers.set("content-type", "application/json");
headers.set("other-header", "foo");
也可以調(diào)用putHeader
方法直接添加請(qǐng)求頭。
HttpRequest<Buffer> request = client.get(8080, "myserver.mycompany.com", "/some-uri");
request.putHeader("content-type", "application/json");
request.putHeader("other-header", "foo");
重用請(qǐng)求
如果需要對(duì)同一個(gè)地址發(fā)起多次請(qǐng)求瓷马,我們可以設(shè)置一次請(qǐng)求拴还,然后重復(fù)使用它。
HttpRequest<Buffer> get = client.get(8080, "myserver.mycompany.com", "/some-uri");
get.send(ar -> {
if (ar.succeeded()) {
// Ok
}
});
// 重復(fù)使用
get.send(ar -> {
if (ar.succeeded()) {
// Ok
}
});
超時(shí)
發(fā)起請(qǐng)求的時(shí)候可以設(shè)置超時(shí)值欧聘,單位是毫秒片林。
client
.get(8080, "myserver.mycompany.com", "/some-uri")
.timeout(5000)
.send(ar -> {
if (ar.succeeded()) {
// Ok
} else {
// Might be a timeout when cause is java.util.concurrent.TimeoutException
}
});
處理請(qǐng)求
處理請(qǐng)求也是異步的。這里的ar類(lèi)型實(shí)際是AsyncResult
的類(lèi)型怀骤,代表異步結(jié)果费封。如果結(jié)果成功了,調(diào)用result()
方法返回HttpResponse<Buffer>
類(lèi)型對(duì)象晒喷,這就是我們發(fā)起請(qǐng)求的結(jié)果孝偎,調(diào)用statusCode()
、body()
等方法就可以查看相應(yīng)結(jié)果了凉敲。
webClient.get("www.baidu.com", "/")
.send(ar -> {
if (ar.succeeded()) {
HttpResponse<Buffer> response = ar.result();
System.out.println(response.body());
} else {
System.out.println(ar.cause());
}
});
解碼響應(yīng)
前面的響應(yīng)是以Buffer
形式返回的衣盾。如果我們確定響應(yīng)是普通字符串、Json對(duì)象爷抓、可以和Json映射的POJO類(lèi)以及WriteStream势决,我們還可以解碼響應(yīng)。例如下面就將響應(yīng)體解碼為了JsonObject
對(duì)象蓝撇。
webClient.post("httpbin.org", "/post")
.as(BodyCodec.jsonObject())
.sendBuffer(Buffer.buffer("name=yitian&age=25"), ar -> {
if (ar.succeeded()) {
HttpResponse<JsonObject> response = ar.result();
System.out.println(response.body());
}
});
BodyCodec
類(lèi)還有另外幾個(gè)方法果复,可以將響應(yīng)體解碼為不同類(lèi)型。假如響應(yīng)體比較大渤昌,可以直接將響應(yīng)體轉(zhuǎn)換為輸出流虽抄,以后慢慢讀取走搁。
client
.get(8080, "myserver.mycompany.com", "/some-uri")
.as(BodyCodec.pipe(writeStream))
.send(ar -> {
if (ar.succeeded()) {
HttpResponse<Void> response = ar.result();
System.out.println("Received response with status code" + response.statusCode());
} else {
System.out.println("Something went wrong " + ar.cause().getMessage());
}
});
如果確定不需要響應(yīng)體,可以直接用none()
方法扔掉響應(yīng)體迈窟。
client
.get(8080, "myserver.mycompany.com", "/some-uri")
.as(BodyCodec.none())
.send(ar -> {
if (ar.succeeded()) {
HttpResponse<Void> response = ar.result();
System.out.println("Received response with status code" + response.statusCode());
} else {
System.out.println("Something went wrong " + ar.cause().getMessage());
}
});
當(dāng)然私植,如果響應(yīng)體還是解碼為Buffer
,我們?nèi)匀豢梢哉{(diào)用bodyAsXXX
方法來(lái)解碼響應(yīng)體车酣。這種方法僅適用于Buffer
響應(yīng)體曲稼。
client
.get(8080, "myserver.mycompany.com", "/some-uri")
.send(ar -> {
if (ar.succeeded()) {
HttpResponse<Buffer> response = ar.result();
// Decode the body as a json object
JsonObject body = response.bodyAsJsonObject();
System.out.println("Received response with status code" + response.statusCode() + " with body " + body);
} else {
System.out.println("Something went wrong " + ar.cause().getMessage());
}
});
使用HTTPS
前面使用的都是普通的HTTP,如果要使用HTTPS連接也很容易湖员,將端口號(hào)指定為443即可贫悄。
client
.get(443, "myserver.mycompany.com", "/some-uri")
.ssl(true)
.send(ar -> {
if (ar.succeeded()) {
// Obtain response
HttpResponse<Buffer> response = ar.result();
System.out.println("Received response with status code" + response.statusCode());
} else {
System.out.println("Something went wrong " + ar.cause().getMessage());
}
});
或者使用絕對(duì)路徑標(biāo)志的URI也可以。
client
.getAbs("https://myserver.mycompany.com:4043/some-uri")
.send(ar -> {
if (ar.succeeded()) {
// Obtain response
HttpResponse<Buffer> response = ar.result();
System.out.println("Received response with status code" + response.statusCode());
} else {
System.out.println("Something went wrong " + ar.cause().getMessage());
}
});
官方文檔的最后還介紹了RxJava的一些集成娘摔。不過(guò)由于我還沒(méi)學(xué)習(xí)過(guò)RxJava窄坦,所以這部分就不介紹了。有興趣的同學(xué)可以查閱相關(guān)資料來(lái)進(jìn)行自學(xué)晰筛。