httpclient總結


1、httpclient總結:
一、基本知識准備
(1)構建URI工具類,URIBuilder
(2)HttpResponse類,可以添加Header信息
獲取所有Header信息的方法,調用HeaderIterator接口

HeaderIterator it = response.headerIterator("Set-Cookie");
while (it.hasNext()) {
System.out.println(it.next());
}

 


(3)HttpEntity內容實體 可以被裝入Request和Response中..
只有獨立的entity才可以被重復調用.
當請求需要entity HttpEntity.writeTo(OutputStream)
從響應中解析entity HttpEntity.getContent()
HttpEntity.getContentType()
HttpEntity.getContentLength()
HttpEntity.getContentEncoding()
對entity進行解析可采用流的方式或者調用EntityUtils,但后者有長度的限制2048
利用 BufferedEntity可以將entity緩存到本地磁盤,用來進行多次讀取.
創建entity信息時需要指定meta信息,包括contentType
(4)可以調用ResponseHandler寫入響應統一處理


二、常用策略
keep-Alieve策略:自定義ConnectionKeepAliveStrategy
重定向策略:LaxRedirectStrategy
三、資源分配
當CloseableHttpClient不再需要,並且不再連接管理的范圍,需要調用CloseableHttpClient.close()方法將其關閉..
四、HttpClient狀態管理
1、在HTTP上下文中,很多有邏輯關系的請求都可以放入到同一個session中..
HttpClient本身線程HttpContext 包含任意的鍵值對,因此線程不安全..通常建議每個線程擁有自己的上下文
2、自動恢復機制---->HttpRequestRetryHandler

HttpRequestRetryHandler myRetryHandler = new HttpRequestRetryHandler() {
public boolean retryRequest(IOException exception,int executionCount,HttpContext context) {
if (executionCount >= 5) {
// Do not retry if over max retry count
return false;
}
if (exception instanceof InterruptedIOException) {
// Timeout
return false;
}
if (exception instanceof UnknownHostException) {
// Unknown host
return false;
}
if (exception instanceof ConnectTimeoutException) {
// Connection refused
return false;
}
if (exception instanceof SSLException) {
// SSL handshake exception
return false;
}
HttpClientContext clientContext = HttpClientContext.adapt(context);
HttpRequest request = clientContext.getRequest();
boolean idempotent = !(request instanceof HttpEntityEnclosingRequest);
if (idempotent) {
// Retry if the request is considered idempotent
return true;
}
return false;
}
};
CloseableHttpClient httpclient = HttpClients.custom()
.setRetryHandler(myRetryHandler)
.build();

 


4、多線程中的應用AtomicInteger,,,,待研究...

從連接管理器中獲取連接
(1)通過HttpClientConnectionManager來管理一個連接
HttpClientContext context = HttpClientContext.create();
HttpClientConnectionManager connMrg = new BasicHttpClientConnectionManager();
HttpRoute route = new HttpRoute(new HttpHost("www.yeetrack.com", 80));
// 獲取新的連接. 這里可能耗費很多時間
ConnectionRequest connRequest = connMrg.requestConnection(route, null);
// 10秒超時
HttpClientConnection conn = connRequest.get(10, TimeUnit.SECONDS);
try {
// 如果創建連接失敗
if (!conn.isOpen()) {
// establish connection based on its route info
connMrg.connect(conn, route, 1000, context);
// and mark it as route complete
connMrg.routeComplete(conn, route, context);
}
// 進行自己的操作.
} finally {
connMrg.releaseConnection(conn, null, 1, TimeUnit.MINUTES);
}
通過更復雜的PoolingHttpClientConnectionManager來管理多個連接,適合多線程中的請求
PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();
// 將最大連接數增加到200
cm.setMaxTotal(200);
// 將每個路由基礎的連接增加到20
cm.setDefaultMaxPerRoute(20);
//將目標主機的最大連接數增加到50
HttpHost localhost = new HttpHost("www.yeetrack.com", 80);
cm.setMaxPerRoute(new HttpRoute(localhost), 50);

CloseableHttpClient httpClient = HttpClients.custom()
.setConnectionManager(cm)
.build();
示例1---------------------------------
PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();
CloseableHttpClient httpClient = HttpClients.custom()
.setConnectionManager(cm)
.build();

// URL列表數組
String[] urisToGet = {
"http://www.domain1.com/",
"http://www.domain2.com/",
"http://www.domain3.com/",
"http://www.domain4.com/"
};

// 為每個url創建一個線程,GetThread是自定義的類
GetThread[] threads = new GetThread[urisToGet.length];
for (int i = 0; i < threads.length; i++) {
HttpGet httpget = new HttpGet(urisToGet[i]);
threads[i] = new GetThread(httpClient, httpget);
}

// 啟動線程
for (int j = 0; j < threads.length; j++) {
threads[j].start();
}

// join the threads
for (int j = 0; j < threads.length; j++) {
threads[j].join();
}
自定義類GetThread
static class GetThread extends Thread {

private final CloseableHttpClient httpClient;
private final HttpContext context;
private final HttpGet httpget;

public GetThread(CloseableHttpClient httpClient, HttpGet httpget) {
this.httpClient = httpClient;
this.context = HttpClientContext.create();
this.httpget = httpget;
}

@Override
public void run() {
try {
CloseableHttpResponse response = httpClient.execute(
httpget, context);
try {
HttpEntity entity = response.getEntity();
} finally {
response.close();
}
} catch (ClientProtocolException ex) {
// Handle protocol errors
} catch (IOException ex) {
// Handle I/O errors
}
}

}

 

注意:即使httpclient可以被多線程訪問,仍建議每個httpclient采用自己的context

5、 public static class IdleConnectionMonitorThread extends Thread {

private final HttpClientConnectionManager connMgr;
private volatile boolean shutdown;

public IdleConnectionMonitorThread(HttpClientConnectionManager connMgr) {
super();
this.connMgr = connMgr;
}

@Override
public void run() {
try {
while (!shutdown) {
synchronized (this) {
wait(5000);
// 關閉失效的連接
connMgr.closeExpiredConnections();
// 可選的, 關閉30秒內不活動的連接
connMgr.closeIdleConnections(30, TimeUnit.SECONDS);
}
}
} catch (InterruptedException ex) {
// terminate
}
}

public void shutdown() {
shutdown = true;
synchronized (this) {
notifyAll();
}
}

}

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM