關於HttpClient不多說,可以到apache網站下載,網上文檔的也多如牛毛。針對HttpClient-3.1,我認為比較重要的一部分就是配置HTTP的參數。實際上,按HttpClient預設的參數配置也可以做簡單的應用,其中對於參數配置問題,我覺得雖然比較亂,但是掌握了HttpClient應用參數繼承的繼承機制,就非常明白了。
HttpClient-3.1中,參數繼承結構:
global--+ | DefaultHttpParams
| |
client | HttpClient
| |
+-- connection manager | HttpConnectionManager
| | |
| +-- connection | HttpConnection
| |
+-- host | HostConfiguration
| |
+-- method | HttpMethod
HttpClient中配置HTTP參數通過上面的繼承結構可以看到,HttpClient在參數配置上分為6個層級,分別為:global、client、connection manager、connection、host、method。下面結合HttpClient-3.1的文檔和原始碼,說說這6個層級的含義。
HttpClient參數配置因為分為6個層級,可能導致在HttpClient參數的重複配置。但是,文檔上也說明了,HttpClient在工作的過程中,是按照繼承層次尋找參數配置,如果在某個最低層級上沒有配置某個參數,程式會自動向上一層級尋找,直到尋找到該參數在某個層級中被配置過,然後運行時按照,距離參數配置層級最低層最近的原則,進行配置。如果都沒有配置,自然就按global層級執行。
當你建立HttpClient和HttpMethod執行個體的時候,可以不用配置就執行HttpMethod,它會按照global層級配置,如果你對它們進行了配置,而且參數配置層級低於global層級,global層級參數配置就被覆蓋。通過上面的繼承層次可以看到,每個不同的層級都對應著一個實體,從高到低依次為DefaultHttpParams、HttpClient、HttpConnectionManager、HttpConnection、HostConfiguration、HttpMethod。
關於各個層級是如何規定的,並在都可以配置哪些參數,可以參考Apache官方網站協助文檔http://hc.apache.org/httpclient-3.x/preference-api.html,下面舉個例子說明一下:
主要通過使用http.socket.timeout參數,其中,HttpClient、HttpConnectionManager、HttpMethod都可以對幹參數進行配置,代碼如下所示:
package org.shirdrn.test;
import java.io.IOException;
import org.apache.commons.httpclient.HostConfiguration;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.HttpMethodBase;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.URI;
import org.apache.commons.httpclient.URIException;
import org.apache.commons.httpclient.methods.GetMethod;
public class MyHttpClient {
private HttpClient client;
private HttpMethodBase method;
private String stringData;
public MyHttpClient() {
this.client = new HttpClient();
this.method = new GetMethod();
}
public void setParams(String url) throws URIException, NullPointerException {
this.client.getParams().setParameter("http.socket.timeout", 1); // 為HttpClient設定參數
this.client.getHttpConnectionManager().getParams().setParameter("http.socket.timeout", 1); // 為HttpConnetionManager設定參數
this.method.getParams().setParameter("http.socket.timeout", 10000); // 為HttpMethod設定參數
HostConfiguration hostConf = new HostConfiguration();
hostConf.setHost(new URI(url, true));
this.client.setHostConfiguration(hostConf);
}
public void execute() throws HttpException, IOException {
int status = this.client.executeMethod(this.method);
if(status == HttpStatus.SC_OK) {
this.stringData = new String(this.method.getResponseBody(), "gb2312");
}
}
public void print() {
System.out.println(this.stringData);
}
public static void main(String[] args) {
MyHttpClient client = new MyHttpClient();
try {
client.setParams("http://www.csdn.net");
client.execute();
client.print();
} catch (Exception e) {
e.printStackTrace();
}
}
}
上面程式中,分別對HttpClient、HttpConnectionManager、HttpMethod三個層級配置了http.socket.timeout參數,直接運行可以看到指定網站的頁面資料被下載下來,可見,是HttpMethod設定的逾時參數起作用了。所以它的層級在上述三個層級中是最低的。
可以測試一下,將HttpConnectionManager、HttpMethod設定的參數全部注釋掉,再執行上述程式,就會發生Socket逾時異常:
java.net.SocketTimeoutException: Read timed out
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.read(SocketInputStream.java:129)
at java.io.BufferedInputStream.fill(BufferedInputStream.java:218)
at java.io.BufferedInputStream.read(BufferedInputStream.java:237)
at org.apache.commons.httpclient.HttpParser.readRawLine(HttpParser.java:78)
at org.apache.commons.httpclient.HttpParser.readLine(HttpParser.java:106)
at org.apache.commons.httpclient.HttpConnection.readLine(HttpConnection.java:1116)
at org.apache.commons.httpclient.HttpMethodBase.readStatusLine(HttpMethodBase.java:1973)
at org.apache.commons.httpclient.HttpMethodBase.readResponse(HttpMethodBase.java:1735)
at org.apache.commons.httpclient.HttpMethodBase.execute(HttpMethodBase.java:1098)
at org.apache.commons.httpclient.HttpMethodDirector.executeWithRetry(HttpMethodDirector.java:398)
at org.apache.commons.httpclient.HttpMethodDirector.executeMethod(HttpMethodDirector.java:171)
at org.apache.commons.httpclient.HttpClient.executeMethod(HttpClient.java:397)
at org.apache.commons.httpclient.HttpClient.executeMethod(HttpClient.java:323)
at org.shirdrn.test.MyHttpClient.execute(MyHttpClient.java:35)
at org.shirdrn.test.MyHttpClient.main(MyHttpClient.java:49)
因為HttpClient設定了Socket逾時時間為1ms,肯定是不能夠擷取到指定網站的資料的。