HttpClient系列-基礎知識(一)

簡述

今天開始介紹下Apache HttpClient 4的全面指南,從基礎到高級進階,本文是基礎知識一。java

狀態碼

從Http響應中得出狀態碼

發送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配置超時

這些參數中更重要的 - 即前兩個 - 也能夠經過更安全的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配置超時

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();
複製代碼

這是以類型安全且可讀的方式配置全部三個超時的推薦方法。

超時屬性說明

如今,讓咱們解釋一下這些不一樣類型的超時意味着什麼:

  • 鏈接超時(http.connection.timeout) - 創建與遠程主機的鏈接的時間
  • socket超時(http.socket.timeout) - 等待數據的時間-創建鏈接後; 兩個數據包之間的最長不活動時間
  • 鏈接管理器超時(http.connection-manager.timeout) - 從鏈接管理器/池中獲取一個鏈接的等待時間。

前兩個參數,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.Timerjava.util.TimerTask來設置一個簡單的延遲任務,該任務在5秒強制超時後停止HTTP GET請求。

DNS循環超時

一些較大的域名將使用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
//...
複製代碼

小結

本文介紹了狀態碼和超時的配置以及機制,但願對你有所幫助。

相關文章
相關標籤/搜索