4.1 send()方法,BodyHandlers
您已經完成瞭如何形成http 請求的學習,因此您可以繼續進行最重要的事情 - 發送此請求。在最簡單的情況下,這很容易做到:
HttpRequest request = HttpRequest.newBuilder(new URI("https://codegym.cc")).build();
HttpClient client = HttpClient.newBuilder()
.version(Version.HTTP_1_1)
.build();
HttpResponse<String> response = client.send(request, BodyHandlers.ofString());
System.out.println(response.statusCode() );
System.out.println(response.body() );
這些是什麼BodyHandlers
?你怎麼認為?您發送了一個請求,這意味著您應該收到一個答复 - http response
。這個響應可以有response body
:一個字符串、一個文件、一個字節數組、一個 InputStream。
是的,是的,沒錯。就像在形成請求時,您需要指定response body
響應的類型。一共可以有8塊:
BodyHandlers.ofByteArray
BodyHandlers.ofString
BodyHandlers.ofFile
BodyHandlers.discarding
BodyHandlers.replacing
BodyHandlers.ofLines
BodyHandlers.fromLineSubscriber
根據BodyHandlers
您傳遞給方法的類型send()
,它會返回這樣的結果類型。例子:
// response body is ignored
HttpResponse<Void> response = client.send(request, BodyHandlers.discarding());
// response body is a string
HttpResponse<String>response = client.send(request, BodyHandlers.ofString());
// response body is a file
HttpResponse<Path> response = client.send(request, BodyHandlers.ofFile(Paths.get("readme.txt")));
// response body is an InputStream
HttpResponse<InputStream> response = client.send(request, BodyHandlers.ofInputStream());
如果應將文件作為響應發送給您,則BodyHandlers.ofFile()
需要將本地文件的名稱傳遞給該方法,該文件將由 HttpClient 對象保存在該方法中。
4.2 followRedirects()方法
301
此外,在發送請求時,您可以指定如果服務器發送或302
(臨時或永久重定向)響應HttpClient 應該做什麼。假設服務器發送了一個代碼302
,您需要:跟踪這種情況,從響應中獲取新的 URL,並將請求發送到新地址。
我不太願意這樣做,特別是考慮到這種情況很常見並且在所有 http 客戶端中早已實現自動化。同樣在此 HttpClient 中,您只需要指定發送請求時選擇的重定向模式。
HttpResponse response = HttpClient.newBuilder()
.followRedirects( HttpClient.Redirect.ALWAYS )
.build()
.send(request, BodyHandlers.ofString());
重定向只有 3 個選項:
- ALWAYS——一直;
- NEVER——從不;
- 正常- 總是,除了 HTTPS -> HTTP。
如您所見,這裡的選項不多,但有定制能力總比沒有好。
4.4 proxy() 方法
還有一些更有用但不常用的選項。在你需要它們之前你不需要它們:)
第一個是代理。在日常生活中,你不會經常遇到它們,但很多大公司內部都有復雜的互聯網流量安全系統,因此代理設置也各不相同。
好吧,當然,您的軟件將在這樣一家公司的內部某個地方運行,總有一天會遇到需要使用代理的事實。因此,這裡也有這樣的選擇是件好事。
設置代理非常簡單 - 例如:
HttpResponse<String> response = HttpClient.newBuilder()
.proxy( ProxySelector.getDefault())
.build()
.send(request, BodyHandlers.ofString());
此處已選擇默認代理,但您可能需要設置自己的代理:
HttpResponse response = HttpClient.newBuilder()
.proxy(ProxySelector.of(new InetSocketAddress("proxy.microsoft.com", 80)))
.build()
.send(request, BodyHandlers.ofString());
我們不會考慮如何使用代理,因為這不包括在本課程的範圍內。
4.5 驗證器()
還有一點很重要。HTTP 協議支持身份驗證。就在協議級別。
現在這種方法幾乎不用了,但大約 20 年前它很常見。Http 請求如下所示:
http://username@example.com/
或者甚至像這樣:
http://username:password@example.com/
這不是郵件。這正是鏈接。是的,你不這麼認為。可以在 http 請求中直接指定登錄名甚至密碼。是的,即使現在你也可以。這就是為什麼我寫道,現在通常沒有人這樣做。但是有這樣的可能。
Authenticator auth = new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(
"username",
"password".toCharArray());
}
};
HttpResponse<String> response = HttpClient.newBuilder()
.authenticator(auth).build()
.send(request, BodyHandlers.ofString());
這很有趣!你知道為什麼而不是“password"
在它說的代碼中"password".toCharArray()
嗎?
因為構造函數的第二個參數PasswordAuthentication
不是String
,而是CharArray
。
為什麼第二個參數不是String
,嗯CharArray
?
因為為了安全起見,所有的密碼都不允許作為一個完整的字符串存儲,即使是在你自己的應用程序中也是如此。也就是說,您的應用程序在其內存中不應將密碼存儲為字符串。這樣一來,如果有人弄濕了記憶,就無法從中提取密碼...
但與此同時,密碼可以通過不安全的 HTTP 協議傳輸到半個世界 :) :) :)
出色地。世界並不完美。
您可以在以下鏈接中閱讀有關此主題的更多信息: