日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

Java HttpClient使用小结

發(fā)布時間:2024/2/28 java 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java HttpClient使用小结 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

轉載自?https://blog.csdn.net/bhq2010/article/details/9210007

httpclient是apache的一個項目:http://hc.apache.org/

文檔比較完善:http://hc.apache.org/httpcomponents-client-ga/tutorial/html/

這里就不啰嗦了,主要是在做demo的時候遇到的一些問題在這里總結一下:

[引用請注明出處http://blog.csdn.net/bhq2010/article/details/9210007]

1、使用連接池
雖說http協(xié)議時無連接的,但畢竟是基于tcp的,底層還是需要和服務器建立連接的。對于需要從同一個站點抓取大量網頁的程序,應該使用連接池,否則每次抓取都和Web站點建立連接、發(fā)送請求、獲得響應、釋放連接,一方面效率不高,另一方面稍不小心就會疏忽了某些資源的釋放、導致站點拒絕連接(很多站點會拒絕同一個ip的大量連接、防止DOS攻擊)。

連接池的例程如下:

SchemeRegistry schemeRegistry = new SchemeRegistry();
?? ?schemeRegistry.register(new Scheme("http", 80, PlainSocketFactory.getSocketFactory()));
schemeRegistry.register(new Scheme("https", 443, SSLSocketFactory.getSocketFactory()));
PoolingClientConnectionManager cm = new PoolingClientConnectionManager(schemeRegistry);
?? ?cm.setMaxTotal(200);
?? ?cm.setDefaultMaxPerRoute(2);
?? ?HttpHost googleResearch = new HttpHost("research.google.com", 80);
?? ?HttpHost wikipediaEn = new HttpHost("en.wikipedia.org", 80);
?? ?cm.setMaxPerRoute(new HttpRoute(googleResearch), 30);
?? ?cm.setMaxPerRoute(new HttpRoute(wikipediaEn), 50);

SchemaRegistry的作用是注冊協(xié)議的默認端口號。PoolingClientConnectionManager是池化連接管理器,即連接池,setMaxTotal設置連接池的最大連接數(shù),setDefaultMaxPerRoute設置每個路由(http://hc.apache.org/httpcomponents-client-ga/tutorial/html/connmgmt.html#d5e467)上的默認連接個數(shù),setMaxPerRoute則單獨為某個站點設置最大連接個數(shù)。
從連接池中獲取http client也很方面:

DefaultHttpClient client = new DefaultHttpClient(cm);

2、設置HttpClient參數(shù)
HttpClient需要設置合適的參數(shù),才能更好地工作。默認的參數(shù)能夠應付少量的抓取工作,但找到一組合適的參數(shù)往往能改善特定情況下的抓取效果。設置參數(shù)的例程如下:

?? ??? ?DefaultHttpClient client = new DefaultHttpClient(cm);
?? ??? ?Integer socketTimeout = 10000;
?? ??? ?Integer connectionTimeout = 10000;
?? ??? ?final int retryTime = 3;
?? ??? ?client.getParams().setParameter(CoreConnectionPNames.SO_TIMEOUT, socketTimeout);
?? ??? ?client.getParams().setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, connectionTimeout);
?? ??? ?client.getParams().setParameter(CoreConnectionPNames.TCP_NODELAY, false);
?? ??? ?client.getParams().setParameter(CoreConnectionPNames.SOCKET_BUFFER_SIZE, 1024 * 1024);
?? ??? ?HttpRequestRetryHandler myRetryHandler = new HttpRequestRetryHandler()
?? ??? ?{
?? ??? ??? ?@Override
?? ??? ??? ?public boolean retryRequest(IOException exception, int executionCount, HttpContext context)
?? ??? ??? ?{
?? ??? ??? ??? ?if (executionCount >= retryTime)
?? ??? ??? ??? ?{
?? ??? ??? ??? ??? ?// 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 ConnectException)
?? ??? ??? ??? ?{
?? ??? ??? ??? ??? ?// Connection refused
?? ??? ??? ??? ??? ?return false;
?? ??? ??? ??? ?}
?? ??? ??? ??? ?if (exception instanceof SSLException)
?? ??? ??? ??? ?{
?? ??? ??? ??? ??? ?// SSL handshake exception
?? ??? ??? ??? ??? ?return false;
?? ??? ??? ??? ?}
?? ??? ??? ??? ?HttpRequest request = (HttpRequest) context.getAttribute(ExecutionContext.HTTP_REQUEST);
?? ??? ??? ??? ?boolean idempotent = !(request instanceof HttpEntityEnclosingRequest);
?? ??? ??? ??? ?if (idempotent)
?? ??? ??? ??? ?{
?? ??? ??? ??? ??? ?// Retry if the request is considered idempotent
?? ??? ??? ??? ??? ?return true;
?? ??? ??? ??? ?}
?? ??? ??? ??? ?return false;
?? ??? ??? ?}
?
?? ??? ?};
?? ??? ?client.setHttpRequestRetryHandler(myRetryHandler);

5、6行分別設置了Socket最大等待時間、連接最大等待時間(單位都是毫秒)。socket等待時間是指從站點下載頁面和數(shù)據(jù)時,兩個數(shù)據(jù)包之間的最大時間間隔,超過這個時間間隔,httpclient就認為連接出了故障。連接最大等待時間則是指和站點建立連接時的最大等待時間,超過這個時間站點不給回應,則認為站點無法連接。第7行設置httpclient不使用NoDelay策略。如果啟用了NoDelay策略,httpclient和站點之間傳輸數(shù)據(jù)時將會盡可能及時地將發(fā)送緩沖區(qū)中的數(shù)據(jù)發(fā)送出去、而不考慮網絡帶寬的利用率,這個策略適合對實時性要求高的場景。而禁用了這個策略之后,數(shù)據(jù)傳輸會采用Nagle's algorithm發(fā)送數(shù)據(jù),該算法會充分顧及帶寬的利用率,而不是數(shù)據(jù)傳輸?shù)膶崟r性。第8行設置socket緩沖區(qū)的大小(單位為字節(jié)),默認是8KB。
HttpRequestRetryHandler是負責處理請求重試的接口。在該接口的內部類中實現(xiàn)RetryRequest方法即可。當httpclient發(fā)送請求之后出現(xiàn)異常時,就會調用這個方法。在該方法中根據(jù)已執(zhí)行請求的次數(shù)、請求內容、異常信息判斷是否繼續(xù)重試,若繼續(xù)重試返回true,否則返回false。
3、設置request header
設置request header也是很重要的,比如設置User-Agent可以將抓取程序偽裝成瀏覽器,騙過一些網站對爬蟲的檢查,設置Accept-Encoding為gzip可以建議站點以壓縮格式傳輸數(shù)據(jù)、節(jié)省帶寬等等。例程如下:
?? ??? ?HttpResponse response = null;
?? ??? ?HttpGet get = new HttpGet(url);
?? ??? ?get.addHeader("Accept", "text/html");
?? ??? ?get.addHeader("Accept-Charset", "utf-8");
?? ??? ?get.addHeader("Accept-Encoding", "gzip");
?? ??? ?get.addHeader("Accept-Language", "en-US,en");
?? ??? ?get.addHeader("User-Agent", "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.22 (KHTML, like Gecko) Chrome/25.0.1364.160 Safari/537.22");
?? ??? ?response = client.execute(get);
?? ??? ?HttpEntity entity = response.getEntity();
?? ??? ?Header header = entity.getContentEncoding();
?? ??? ?if (header != null)
?? ??? ?{
?? ??? ??? ?HeaderElement[] codecs = header.getElements();
?? ??? ??? ?for (int i = 0; i < codecs.length; i++)
?? ??? ??? ?{
?? ??? ??? ??? ?if (codecs[i].getName().equalsIgnoreCase("gzip"))
?? ??? ??? ??? ?{
?? ??? ??? ??? ??? ?response.setEntity(new GzipDecompressingEntity(entity));
?? ??? ??? ??? ?}
?? ??? ??? ?}
?? ??? ?}
?? ??? ?return response;

各個header的含義參考http://kb.cnblogs.com/page/92320/
需要的都設上就好了。如果需要很多不同的User-Agent輪流使用(同一個User-Agent對一個站點頻繁訪問容易被識別為爬蟲而杯具),可以去網上找,也可以在自己的chrome瀏覽器里看或者用抓包軟件抓。值得注意的是設置了Accept-Encoding為gzip之后,對站點回復的內容要檢查是否是壓縮格式的,如果是,則解壓縮,如上面例程中第9行之后的代碼所示。
[引用請注明出處http://blog.csdn.net/bhq2010/article/details/9210007]
?

超強干貨來襲 云風專訪:近40年碼齡,通宵達旦的技術人生

總結

以上是生活随笔為你收集整理的Java HttpClient使用小结的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。