Vert.x(vertx)發送 HTTP/HTTPS請求


 Vert.x Web服務有兩種協議,一種是HTTP,另外一種是使用ssl的HTTPS,請求的方式有五種,分別是get、post、put、delete、head。為了簡單,服務端主要實現對HTTP協議的get和post的請求處理。如下

 1 @Override
 2 public void start() throws Exception {
 3  
 4     HttpServer server = vertx.createHttpServer();
 5     Router router = Router.router(vertx);
 6  
 7     // 處理get請求
 8     router.get("/get").handler(request -> {
 9         String username = request.request().getParam("username");
10         String password = request.request().getParam("password");
11  
12         System.out.println(username + " " + password);
13  
14         request.response().end("get request success");
15     });
16  
17     // 處理post請求
18     router.post("/post").handler(request -> {
19         request.request().bodyHandler(body->{
20             System.out.println(body.toJsonObject().toString());
21             JsonObject responseData = new JsonObject()
22                     .put("msg","success");
23             request.response().end(responseData.toString());
24         });
25     });
26  
27     server.requestHandler(router::accept);
28     server.listen(80);
29  
30 }

上面的代碼就是創建了一個Web服務,監聽/get和/post地址,分別處理get請求和post請求。如果對上面的代碼不理解的朋友可以參考《創建HTTP服務》 和 《Web開發 - 路由》

發送HTTP GET請求

GET請求對於一些敏感信息非常容易泄露。

 1 @Override
 2 public void start() throws Exception {
 3     // 創建WebClient,用於發送HTTP或者HTTPS請求
 4     WebClient webClient = WebClient.create(vertx);
 5     // 以get方式請求遠程地址
 6     webClient.getAbs("http://localhost/get").send(handle -> {
 7         // 處理響應的結果
 8         if (handle.succeeded()) {
 9         // 這里拿到的結果就是一個HTML文本,直接打印出來
10         System.out.println(handle.result().bodyAsString());
11         }
12     });
13 }

這是最簡單的一種請求方式,在上面的代碼中,首先創建了WebClient對象,通過WebClient可以方便的發送HTTP請求。有朋友可能會注意到,在Vert.x提供的核心包中有HttpClient,可以通過Vert.x實例獲取

HttpClient httpClient = vertx.createHttpClient();

HTTPClient這個接口也可以發送HTTP請求,只是它比較低級,如果在請求中帶復雜數據,附帶請求頭,封裝響應結果都需要自己來處理。因此,Vert.x提供了vertx-web-client的支持。

WebClient的API非常簡單,發送GET請求,可以使用getAbs。Abs是絕對地址的意思,除了使用絕對地址,還可以使用域名+端口號+請求地址的方式,代碼如下:

1 webClient.get(80, "localhost", "/get").send(handle -> {
2     // 處理響應的結果
3     if (handle.succeeded()) {
4         // 這里拿到的結果就是一個HTML文本,直接打印出來
5         System.out.println(handle.result().bodyAsString());
6     }
7 });

第一個參數是端口號,第二個參數是域名,第三個參數是請求地址。

發送HTTP請求 請求頭

HTTP協議包含三部分,請求行、請求頭和請求體。一般來講,不建議在GET請求的請求體中帶數據,但請求頭數據是每個請求都有的,比如使用User-Agent指定設備的類型以及操作系統等等。我們在請求遠程服務的時候,如何設置請求頭呢,代碼如下

1 webClient.get(80, "localhost", "/get")
2 .putHeader("User-Agent","Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:65.0) Gecko/20100101 Firefox/65.0")
3 .send(handle -> {
4     // 處理響應的結果
5     if (handle.succeeded()) {
6         // 這里拿到的結果就是一個HTML文本,直接打印出來
7         System.out.println(handle.result().bodyAsString());
8     }
9 });

設置超時時間

HTTP請求是一個耗時操作,受到網絡等因素的影響,很多時候我們要限制一個最大的請求時間,超過這個時間就不去處理了,可以通過WebClientOptions設置

 1 @Override
 2 public void start() throws Exception {
 3     // 創建WebClient,用於發送HTTP或者HTTPS請求
 4     WebClientOptions webClientOptions = new WebClientOptions()
 5     .setConnectTimeout(500); // ms
 6     WebClient webClient = WebClient.create(vertx, webClientOptions);
 7     // 以get方式請求遠程地址
 8     webClient.getAbs("http://localhost/get").send(handle -> {
 9         // 處理響應的結果
10         if (handle.succeeded()) {
11             // 這里拿到的結果就是一個HTML文本,直接打印出來
12             System.out.println(handle.result().bodyAsString());
13         }
14     });
15 }

除了設置超時時間以外,還可以設置是否重定向到頁面以及HTTPS的證書等等。

發送HTTP GET請求 帶數據

很多的情況下在請求服務端的時候都需要帶一些必要的數據,GET請求帶數據有兩種方式,第一種就是在請求的URL后直接拼接參數 ?username=xxx&password=xxx的形式。還有一種方式是通過addQueryParam的方式添加請求參數,如下所示

 1 @Override
 2 public void start() throws Exception {
 3     // 創建WebClient,用於發送HTTP或者HTTPS請求
 4     WebClient webClient = WebClient.create(vertx);
 5     // 以get方式請求遠程地址
 6     webClient
 7     .getAbs("http://localhost/get")
 8     // 通過這種方式發送數據
 9     .addQueryParam("username", "admin")
10     .addQueryParam("password", "admin123")
11     .send(handle -> {
12         // 處理響應的結果
13         if (handle.succeeded()) {
14             // 這里拿到的結果就是一個HTML文本,直接打印出來
15             System.out.println(handle.result().bodyAsString());
16         }
17     });
18 }

上面的代碼就是向服務端發送兩個參數,一個是username一個是password。這兩個參數在網絡上都是通過明文進行傳輸的,因此如果真的是要做登陸,一定不要使用get方式。這里我們並不需要去思考服務端如何接收這兩個參數,客戶端只要能夠保證參數能夠發送出去就可以了。

發送POST請求

GET方式在瀏覽器中使用的還是比較多,但在服務調用中一般比較少,在服務調用中一般會選擇使用POST方式,下面看POST方式請求遠程服務的案例,代碼如下

 1 @Override
 2 public void start() throws Exception {
 3     // 創建WebClient,用於發送HTTP或者HTTPS請求
 4     WebClient webClient = WebClient.create(vertx);
 5     // 以get方式請求遠程地址
 6     webClient.postAbs("http://localhost/post")
 7     .send(handle -> {
 8     // 處理響應的結果
 9     if (handle.succeeded()) {
10         // 這里拿到的結果就是一個HTML文本,直接打印出來
11         System.out.println(handle.result().bodyAsString());
12         }
13     });
14 }

POST方式和GET方式請求在API調用上非常類似,上面的代碼中,只是調用了postAbs方法而已,底層通信協議是如何封裝的開發者完全不用關注,getAbs和postAbs在底層處理方式是完全不同的。

發送POST請求 帶數據

當然了,一般進行服務調用的時候也都需要附帶一些數據,比如我們要調用發短信服務,那么就至少需要附帶手機號和短信內容過去當然還需要一些認證信息,服務提供方發送短信成功之后需要告訴我們已經受理成功,或者僅僅是收到我們的請求。在POST中帶數據的方式比較多,數據類型也多樣化,主要有以下三種類型

1. form表單

2. json字符串

3. xml字符串

第一種數據類型是前后端交互時經常使用的方式,第二、三種方式是服務調用常用的序列化方式。下面以發送JSON字符串的形式來調用遠程服務,代碼如下:

 1 @Override
 2 public void start() throws Exception {
 3     // 創建WebClient,用於發送HTTP或者HTTPS請求
 4     WebClient webClient = WebClient.create(vertx);
 5 
 6     // 構造請求的數據
 7     JsonObject data = new JsonObject()
 8     .put("username", "admin")
 9     .put("password", "admin123");
10 
11     // 以get方式請求遠程地址
12     webClient.postAbs("http://localhost/post")
13     .sendJsonObject(data, handle -> {
14         // 處理響應的結果
15         if (handle.succeeded()) {
16             // 這里拿到的結果就是一個HTML文本,直接打印出來
17             // handle.result().bodyAsJsonObject() 可以解析Json數據
18             System.out.println(handle.result().bodyAsString());
19         }
20     });
21 }

在上面的代碼中,我們先創建了一個JsonObject對象,和GSON和fastjson中的JsonObject類似,但感覺Vert.x提供的JsonObject更為強大一些,通過JsonObject可以非常方便的構造一個Json字符串。當然除了JsonObject以外,Vert.x還提供了JsonArray可以構造一個json數組。

構造一個json對象以后,在請求遠程服務的時候可以通過sendJsonObject方法,將構造好的json對象傳入,Vert.x底層就會給我們把json對象格式化為json字符串,發送給服務提供者。服務提供者就會收到如下請求數據:

1 {
2     "username": "admin",
3     "password": "admin123"
4 }

服務端收到這些數據也可以使用JsonObject對象將字符串轉為json對象,方便的讀寫數據。當然了,服務端收到我們的數據之后進行處理,最后還需要給客戶端響應數據,服務端也可以給客戶端響應json字符串,客戶端同樣可以對json字符串進行處理。

這種案例非常多,可以參考微信支付掃碼接口文檔

https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=9_1

請求HTTPS服務

使用HTTP協議,不管是get請求還是post請求,數據傳輸都是明文傳輸的,因此敏感信息通過HTTP方式都有暴露的危險。現在越來越多的網站都已經升級為HTTPS協議,通過加密的方式進行傳輸,保證敏感信息的安全。

HTTP請求安全簡單來講有兩點,第一個是數據被篡改,第二個是敏感數據被竊取。解決數據篡改的手段是對消息進行簽名,解決數據竊取的手段是加密,HTTPS實際上就是為了解決敏感信息被竊取的問題的。

對於HTTPS的原理這里不做過多的介紹,感興趣的朋友可以在網絡上搜索相關文章,在Vert.x中請求HTTPS也非常簡單,代碼如下:

 1 @Override
 2 public void start() throws Exception {
 3     // 創建WebClient,用於發送HTTP或者HTTPS請求
 4     WebClient webClient = WebClient.create(vertx);
 5     // 以get方式請求遠程地址
 6     webClient.getAbs("https://www.sina.com")
 7     .ssl(true)  8     .send(handle -> {
 9         // 處理響應的結果
10         if (handle.succeeded()) {
11             // 這里拿到的結果就是一個HTML文本,直接打印出來
12             System.out.println(handle.result().bodyAsString());
13         }
14     });
15 }

上面的代碼是我要請求新浪的主頁,可以看到,只需要在調用send方法之前,調用ssl方法,並指定為true即可。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM