今天開始介紹下Apache HttpClient 4的全面指南,從基礎到高級進階,本文是基礎知識一。java
發送Http請求後 - 咱們返回一個org.apache.http.HttpResponse
實例,咱們能夠獲取到響應的狀態行,並隱式地訪問狀態代碼:apache
response.getStatusLine().getStatusCode()
複製代碼
使用它,咱們能夠驗證從服務器收到的代碼是不是正確的:安全
@Test
public void test()
throws ClientProtocolException, IOException {
HttpClient client = HttpClientBuilder.create().build();
HttpResponse response = client.execute(new HttpGet(SAMPLE_URL));
int statusCode = response.getStatusLine().getStatusCode();
assertThat(statusCode, equalTo(HttpStatus.SC_OK));
}
複製代碼
這裏面,使用org.apache.http.HttpStatus
中庫中提供的預約義狀態代碼。bash
HttpClient能夠配置超時的時間,接下來,咱們看下如何使用。服務器
HttpClient的自帶了大量的配置參數,而全部的這些均可以在一個通用的Map集合中來設置。dom
有3個超時參數配置:socket
DefaultHttpClient httpClient = new DefaultHttpClient();
int timeout = 5; // seconds
HttpParams httpParams = httpClient.getParams();
httpParams.setParameter(
CoreConnectionPNames.CONNECTION_TIMEOUT, timeout * 1000);
httpParams.setParameter(
CoreConnectionPNames.SO_TIMEOUT, timeout * 1000);
httpParams.setParameter(
ClientPNames.CONN_MANAGER_TIMEOUT, new Long(timeout * 1000));
複製代碼
這些參數中更重要的 - 即前兩個 - 也能夠經過更安全的API進行設置:ide
DefaultHttpClient httpClient = new DefaultHttpClient();
int timeout = 5; // seconds
HttpParams httpParams = httpClient.getParams();
HttpConnectionParams.setConnectionTimeout(
httpParams, timeout * 1000); // http.connection.timeout
HttpConnectionParams.setSoTimeout(
httpParams, timeout * 1000); // http.socket.timeout
複製代碼
第三個參數在HttpConnectionParams中沒有自定義setter ,它仍然須要經過setParameter方法手動設置。ui
4.3中引入新API來設置超時的方法,這個更方便快捷:spa
int timeout = 5;
RequestConfig config = RequestConfig.custom()
.setConnectTimeout(timeout * 1000)
.setConnectionRequestTimeout(timeout * 1000)
.setSocketTimeout(timeout * 1000).build();
CloseableHttpClient client =
HttpClientBuilder.create().setDefaultRequestConfig(config).build();
複製代碼
這是以類型安全且可讀的方式配置全部三個超時的推薦方法。
如今,讓咱們解釋一下這些不一樣類型的超時意味着什麼:
前兩個參數,connection和socket超時是最重要的。可是,在高負載狀況下設置獲取鏈接的超時很是重要,這就是不該忽略第三個參數的緣由。
雖然設置創建HTTP鏈接和不接收數據的超時很是有用,但有時咱們須要爲整個請求設置強制超時。
例如,可能大型文件的下載符合此類別。在這種狀況下,能夠成功創建鏈接,數據能夠一直經過,可是咱們仍然須要確保操做不會超過某個特定時間閾值。
HttpClient沒有任何容許咱們爲請求設置總超時的配置; 可是,它確實爲請求提供了停止功能,所以咱們能夠利用該機制實現一個簡單的超時機制:
HttpGet getMethod =new HttpGet("http://localhost:8080/");
int hardTimeout = 5; // seconds
TimerTask task = new TimerTask() {
@Override
public void run() {
if (getMethod != null) {
getMethod.abort();
}
}
};
new Timer(true).schedule(task, hardTimeout * 1000);
HttpResponse response = httpClient.execute(getMethod);
System.out.println(
"HTTP Status of response: " + response.getStatusLine().getStatusCode());
複製代碼
咱們正在利用java.util.Timer
和java.util.TimerTask
來設置一個簡單的延遲任務,該任務在5秒強制超時後停止HTTP GET請求。
一些較大的域名將使用DNS循環配置是很常見的,基本上具備映射到多個IP地址的相同域名。這引起了針對此類域的超時的新挑戰,緣由很簡單,由於HttpClient將嘗試鏈接到超時的域:
HttpClient獲取到該域的IP路由列表 它嘗試第一個 - 超時 它嘗試第二個 - 也超時 等等 … 所以,正如你所看到的 - 當咱們指望它時,總體操做不會超時。相反 - 當全部可能的路線超時時它會超時。更重要的是 - 這將徹底透明地發生在客戶端上(除非你在DEBUG級別配置了日誌)。
這是一個能夠運行並複製此問題的簡單示例:
int timeout = 3;
RequestConfig config = RequestConfig.custom().
setConnectTimeout(timeout * 1000).
setConnectionRequestTimeout(timeout * 1000).
setSocketTimeout(timeout * 1000).build();
CloseableHttpClient client = HttpClientBuilder.create()
.setDefaultRequestConfig(config).build();
HttpGet request =new HttpGet("http://www.domain.com");
response = client.execute(request);
複製代碼
你將注意到具備DEBUG日誌級別的重試邏輯:
DEBUG o.a.h.i.c.HttpClientConnectionOperator - Connecting to www.domain.com/173.194.34.212:81
DEBUG o.a.h.i.c.HttpClientConnectionOperator -
Connect to www.domain.com/173.194.34.212:81 timed out. Connection will be retried using another IP address
DEBUG o.a.h.i.c.HttpClientConnectionOperator - Connecting to www.domain.com/173.194.34.208:81
DEBUG o.a.h.i.c.HttpClientConnectionOperator -
Connect to www.domain.com/173.194.34.208:81 timed out. Connection will be retried using another IP address
DEBUG o.a.h.i.c.HttpClientConnectionOperator - Connecting to www.domain.com/173.194.34.209:81
DEBUG o.a.h.i.c.HttpClientConnectionOperator -
Connect to www.domain.com/173.194.34.209:81 timed out. Connection will be retried using another IP address
//...
複製代碼
本文介紹了狀態碼和超時的配置以及機制,但願對你有所幫助。