??介紹
Java 原生 HttpClient 是從 Java 11 開始引入的標準庫,用于簡化 HTTP 請求的發送與響應處理。它支持同步和異步請求,并內置對 HTTP/1.1 和 HTTP/2 協議的支持。HttpClient 提供了易用的 API 來設置請求頭、請求體、處理響應以及配置 SSL/TLS 加密等安全功能。
?
?
一個簡單的例子
發送 GET 請求并將打印 Response
HttpClient client = HttpClient.newBuilder().build();
HttpRequest request = HttpRequest.newBuilder().uri(URI.create("http://localhost:8080/get")).GET().build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());System.out.println(response.statusCode());
System.out.println(response.headers());
System.out.println(response.body());
?
?
核心對象
HttpClient
要發送請求,首先需要通過其構建器創建一個 HttpClient?實例。構建器允許配置客戶端的各種狀態,例如 HTTP 協議版本、是否重定向、超時設置、代理、身份驗證等等,從而定制每個客戶端的行為。
HttpClient client = HttpClient.newBuilder().version(HttpClient.Version.HTTP_2).followRedirects(HttpClient.Redirect.NORMAL).proxy(ProxySelector.of(new InetSocketAddress("www-proxy.com", 8080))).connectTimeout(Duration.ofMillis(200)).authenticator(Authenticator.getDefault()).build();
HttpRequest
HttpRequest 扮演著構建和配置 HTTP 請求的角色,,包括設置請求的 URL、請求方法(如 GET、POST、PUT 等)、請求頭、請求體、超時時間等。HttpRequest 是不可變的,一旦創建后無法修改,只能通過 HttpRequest 的構建器來創建一個定制的請求對象。
HttpRequest request = HttpRequest.newBuilder().uri(URI.create("http://localhost:8080/get")).GET().build();HttpRequest request = HttpRequest.newBuilder().uri(URI.create("http://localhost:8080/post")).header("Content-Type", "application/json").POST(HttpRequest.BodyPublishers.noBody()).timeout(Duration.ofMinutes(1)).build();
?
HttpResponse
HttpResponse 用于表示 HTTP 請求的響應。它封裝了 HTTP 響應的狀態碼、響應體、響應頭、請求 URI、HTTP 協議版本等等。
HttpResponse 的常用方法
- statusCode():獲取 HTTP 響應的狀態碼。
- body():獲取響應體內容。
- headers():獲取所有響應頭。
- uri():獲取響應對應的請求 URI。
- version():獲取響應使用的 HTTP 協議版本。
響應體的處理
響應體是通過 HttpResponse.BodyHandler 來處理的。HttpResponse.BodyHandler 是一個接口,用來定義如何處理響應體的內容。常用的 BodyHandler 有:
- BodyHandlers.ofString():將響應體處理為字符串(適用于文本響應)
- BodyHandlers.ofByteArray():將響應體處理為字節數組(適用于二進制數據,如文件下載)。
- BodyHandlers.ofInputStream():將響應體處理為 InputStream(適用于流式處理)。
- BodyHandlers.ofFile():將響應體直接寫入文件(適用于文件下載等場景)。
?
同步和異步
同步
同步 HttpClient 通過調用 send() 方法來發送請求并等待響應。在請求完成之前,當前線程會被阻塞,即線程會等待直到 HTTP 響應返回并處理結果。
上文給出的例子都是同步請求
特點:
- 阻塞:當前線程會等待直到請求完成并獲取響應。
- 順序執行:代碼會按順序執行,每個請求都必須等待前一個請求完成。
- 適用場景:適合較少的并發請求,或者請求和響應的順序很重要時。
異步
通過調用 sendAsync() 方法來發送請求,該方法立即返回一個 CompletableFuture,而不是直接返回響應。請求會在后臺線程中執行,主線程不會被阻塞。你可以使用 thenAccept()、thenApply() 等方法來處理響應。
特點:
- 非阻塞:不會阻塞當前線程,任務在后臺異步執行。
- 并發執行:允許多個請求并行執行,可以提高效率,尤其是處理大量并發請求時。
- 適用場景:適用于 I/O 密集型任務,如發送多個請求、等待多個響應時。
HttpClient client = HttpClient.newBuilder().build();
HttpRequest request = HttpRequest.newBuilder().uri(URI.create("http://localhost:8080/get")).GET().build();CompletableFuture<HttpResponse<String>> completableFutureResponse = client.sendAsync(request, HttpResponse.BodyHandlers.ofString());
HttpResponse<String> response = completableFutureResponse.get();
?
身份驗證器
Authenticator 是 HttpClient 中用來為 HTTP 請求提供身份驗證信息的核心類。Authenticator 的工作原理是基于 認證挑戰(Authentication Challenge)機制。認證過程的基本步驟如下:
- 客戶端發送請求:客戶端向服務器發出一個 HTTP 請求,可能是沒有認證信息的請求。
- 服務器返回認證挑戰:如果目標資源需要認證,服務器會返回一個 401 Unauthorized 或 407 Proxy Authentication Required 響應,這兩者都表明客戶端沒有提供有效的身份認證信息。
- Authenticator 觸發:當 HttpClient 遇到需要認證的響應時,它會調用 Authenticator 的 getPasswordAuthentication() 方法。這是通過一個回調機制觸發的,Authenticator 可以返回包含用戶名和密碼的 PasswordAuthentication 對象。
- 客戶端再次發送帶認證信息的請求:客戶端將返回的認證信息(如用戶名和密碼)包含在 HTTP 請求的 Authorization 頭部中,再次發送給服務器。
- 認證通過:如果服務器驗證通過,返回相應的資源;否則驗證失敗。
注意:Authenticator 類的設計初衷是為了支持 HTTP 基本認證(Basic Authentication)和 代理認證(Proxy Authentication)等標準認證機制。對于 JWT 認證方式,并沒有提供自動刷新。
?
?
參考
Introduction to the Java HTTP Client
??
?