JDK變化
- 從java9的jdk.incubator.httpclient模塊遷移到java.net.http模塊,包名由jdk.incubator.http改爲java.net.http
- 原來的諸如HttpResponse.BodyHandler.asString()方法變更爲HttpResponse.BodyHandlers.ofString(),變化一爲BodyHandler改爲BodyHandlers,變化二爲asXXX()之類的方法改爲ofXXX(),由as改爲of
- 官方文檔:https://docs.oracle.com/en/java/javase/11/docs/api/java.net.http/java/net/http/package-summary.html
實例
設置超時時間
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
|
HttpConnectTimeoutException實例
1 2 3 4 5 6 7 |
|
HttpTimeoutException實例
1 2 3 4 5 |
|
設置authenticator
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
|
- authenticator可以用來設置HTTP authentication,比如Basic authentication
- 雖然Basic authentication也可以自己設置header,不過通過authenticator省得自己去構造header
設置header
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|
通過request可以自己設置header,多個header可直接傳入可變參數headers(String數組),或者傳入傳統的Map型的header直接流轉換爲headers
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|
GET
同步
1 2 3 4 5 6 7 8 9 10 11 12 |
|
異步
1 2 3 4 5 6 7 8 9 10 11 |
|
POST表單
1 2 3 4 5 6 7 8 9 10 11 12 |
|
header指定內容是表單類型,然後通過BodyPublishers.ofString傳遞表單數據,需要自己構建表單參數
POST JSON
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
|
post json的話,body自己json化爲string,然後header指定是json格式
文件上傳
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
|
- 官方的HttpClient並沒有提供類似WebClient那種現成的BodyInserters.fromMultipartData方法,因此這裏需要自己轉換
- 這裏使用org.apache.httpcomponents(httpclient及httpmime)的MultipartEntityBuilder構建multipartEntity,最後通過HttpRequest.BodyPublishers.ofInputStream來傳遞內容
- 這裏header要指定Content-Type值爲multipart/form-data以及boundary的值,否則服務端可能無法解析
文件下載
1 2 3 4 5 6 7 8 9 10 11 |
|
使用HttpResponse.BodyHandlers.ofFile來接收文件
併發請求
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
|
- sendAsync方法返回的是CompletableFuture,可以方便地進行轉換、組合等操作
- 這裏使用CompletableFuture.allOf組合在一起,最後調用join等待所有future完成
錯誤處理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
|
- HttpClient異步請求返回的是CompletableFuture<HttpResponse<T>>,其自帶exceptionally方法可以用來做fallback處理
- 另外值得注意的是HttpClient不像WebClient那樣,它沒有對4xx或5xx的狀態碼拋出異常,需要自己根據情況來處理,手動檢測狀態碼拋出異常或者返回其他內容
HTTP2
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
|
執行之後可以看到返回的response的version爲HTTP_2
WebSocket
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
|
- HttpClient支持HTTP2,也包含了WebSocket,通過newWebSocketBuilder去構造WebSocket
- 傳入listener進行接收消息,要發消息的話,使用WebSocket來發送,關閉使用sendClose方法
reactive streams
HttpClient本身就是reactive的,支持reactive streams,這裏舉ResponseSubscribers.ByteArraySubscriber的源碼看看:
java.net.http/jdk/internal/net/http/ResponseSubscribers.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 |
|
- BodySubscriber接口繼承了Flow.Subscriber<List<ByteBuffer>>接口
- 這裏的Subscription來自Flow類,該類是java9引入的,裏頭包含了支持Reactive Streams的實現
小結
HttpClient在Java11從incubator變爲正式版,相對於傳統的HttpUrlConnection其提升可不是一點半點,不僅支持異步,也支持reactive streams,同時也支持了HTTP2以及WebSocket,非常值得大家使用。