參考資料:
http://www.systinet.com/doc/wasp_uddi/uddi/igpreliminary.html
教程中的一個例程,能夠下載。
來源:竹筍炒肉
雖然用telnet這樣的程序均可把頁面取回來,可是在與web服務器的交互中,若是涉及cookie或https或ssl等內容,通常功能相對完備的http客戶端仍是很是必要的。IE或NetScape等瀏覽器確實不錯,但是若是爲實現持續互動而在程序調用瀏覽器,我我的認爲其中的工做量仍是不小的,這還沒考慮版權問題。最好的辦法,就是能有一個開源的包,能實現http客戶端的功能,供咱們開發的程序調用。httpclient就是這麼一個包,我相信可能有比它的實現更好的,但目前我只關注這個。:)
html
下面是nogoop作的功能比較表:
java
Features |
nogoop |
Sun JRE < 1.4.2 |
Sun JRE 1.4.2 |
Innovation |
Apache/Jakarta |
cookies |
|
|
|
X |
X |
plug compatible |
X |
X |
X |
X |
[partial] |
true request output stream |
|
|
|
X |
X |
true response input stream |
X |
|
|
X |
X |
connection keep alive |
X |
X |
X |
X |
X |
connection pool throttling |
X |
|
|
|
X |
connection/request timeout |
X |
|
X [uns] |
X |
X |
idle connection timeout |
X |
|
|
|
X |
pipelining of requests |
|
|
|
X |
|
alternate DNS resolution (dnsjava) |
X |
|
|
|
|
SSL |
X |
X |
X |
X |
X |
basic authentication |
X |
X |
X |
X |
X |
digest authentication |
X |
X |
X |
X |
X |
NTLM authentication |
X |
|
[Windows only] |
|
X |
proxy authentication |
X |
X |
X |
X |
X |
minimum JRE version |
1.2 |
1 |
01年4月2日 |
1.2 |
1.2 |
price |
$499 |
free |
free |
free |
free |
source available |
X |
|
|
X |
X |
diagnostic tracing |
X |
|
|
X |
X |
actively supported |
X |
X |
X |
|
X |
fix turnaround |
fast |
slow |
slow |
none |
medium |
license |
purchase |
Sun JRE |
Sun JRE |
LGPL |
Apache |
一、HttpClient的功能
- 基於標準,純正java,實現了http1.0和1.1。
- 在一個可擴展的OO框架內,實現了HTTP的所有方法(GET, POST,
PUT, DELETE, HEAD, OPTIONS, and TRACE)
- 支持HTTPS(ssl上的HTTP)的加密操做
- 透明地穿過HTTP代理創建鏈接
- 經過CONNECT方法,利用經過創建穿過HTTP代理的HTTPS鏈接
- 利用本地Java socket,透明地穿過SOCKS(版本5和4)代理創建鏈接
- 支持利用Basic、Digest和NTLM加密的認證
- 支持用於上傳大文件的Multi-Part表單POST方法
- 插件式安全socket實現,易於使用第三方的解決方案
- 鏈接管理,支持多線程應用,支持設定單個主機總鏈接和最高鏈接數量,自動檢測和關閉失效鏈接
- 直接將請求信息流送到服務器的端口
- 直接讀取從服務器的端口送出的應答信息
- 支持HTTP/1.0中用KeepAlive和HTTP/1.1中用persistance設置的持久鏈接
- 直接訪問由服務器送出的應答代碼和頭部信息
- 可設置鏈接超時時間
- HttpMethods 實現Command Pattern,以容許並行請求或高效鏈接複用
- 遵循the Apache Software License協議,源碼免費可得
二、預備工做
對jre1.3.*,若是要HttpClient支持https,則須要下載並安裝
jsse和
jce.安裝的步驟以下:
1)下載jsse和jce.
2)檢查CLASSPATH中沒有與jsse和jce相關的jar包
3)將 US_export_policy.jar、local_policy.jar、jsse.jar、jnet.jar、jce1_2_x.jar、sunjce_provider.jar、jcert.jar複製到目錄:
UNIX:$JDK_HOME/jre/lib/ext
Windows:%JDK_HOME%\jre\lib\ext
4)修改下述目錄下的java.security文件。
UNIX:$JDK_HOME/jre/lib/security/
Windows:%JDK_HOME%\jre\lib\security\
5)
將
#
# List of providers and their preference orders:
#
security.provider.1=sun.security.provider.Sun
security.provider.2=com.sun.rsajca.Provider
改成:
#
# List of providers and their preference orders:
#
security.provider.1=com.sun.crypto.provider.SunJCE
security.provider.2=sun.security.provider.Sun
security.provider.3=com.sun.rsajca.Provider
security.provider.4=com.sun.net.ssl.internal.ssl.Provider
HttpClient還要求安裝commons-logging,下面跟httpclient一塊安裝。
三、取得源碼
cvs -d :pserver:anoncvs@cvs.apache.org:/home/cvspublic login
password: anoncvs
cvs -d :pserver:anoncvs@cvs.apache.org:/home/cvspublic checkout jakarta-commons/logging
cvs -d :pserver:anoncvs@cvs.apache.org:/home/cvspublic checkout jakarta-commons/httpclient
編譯:
cd jakarta-commons/logging
ant dist
cp dis/*.jar ../httpclient/lib/
cd ../httpclient
ant dist
四、使用HttpClient編程的基本步聚
- 建立 HttpClient 的一個實例.
- 建立某個方法(DeleteMethod,EntityEnclosingMethod,ExpectContinueMethod,GetMethod,HeadMethod,MultipartPostMethod,OptionsMethod,PostMethod,PutMethod,TraceMethod)的一個實例,通常可用要目標URL爲參數。
- 讓 HttpClient 執行這個方法.
- 讀取應答信息.
- 釋放鏈接.
- 處理應答.
在執行方法的過程當中,有兩種異常,一種是HttpRecoverableException,表示偶然性錯誤發生,通常再試可能成功,另外一種是IOException,嚴重錯誤。
這兒有這個教程中的一個例程,能夠
下載。
下面學習與http客戶端相關的認證、重定向等內容。
一、認證
HttpClient三種不一樣的認證方案: Basic, Digest and NTLM. 這些方案可用於服務器或代理對客戶端的認證,簡稱服務器認證或代理認證。
1)服務器認證(Server Authentication)
HttpClient處理服務器認證幾乎是透明的,僅須要開發人員提供登陸信息(login credentials)。登陸信息保存在HttpState類的實例中,能夠經過 setCredentials(String realm, Credentials cred)和getCredentials(String realm)來獲取或設置。注意,設定對非特定站點訪問所須要的登陸信息,將realm參數置爲null. HttpClient內建的自動認證,能夠經過HttpMethod類的setDoAuthentication(boolean doAuthentication)方法關閉,並且此次關閉隻影響HttpMethod當前的實例。
搶先認證(Preemptive Authentication)能夠經過下述方法打開.
client.getState().setAuthenticationPreemptive(true);
在這種模式時,HttpClient會主動將basic認證應答信息傳給服務器,即便在某種狀況下服務器可能返回認證失敗的應答,這樣作主要是爲了減小鏈接的創建。爲使每一個新建的 HttpState實例都實行搶先認證,能夠以下設置系統屬性。
setSystemProperty(Authenticator.PREEMPTIVE_PROPERTY, "true");
Httpclient實現的搶先認證遵循rfc2617.
2)代理認證(proxy authentication)
除了登陸信息需單獨存放之外,代理認證與服務器認證幾乎一致。用 setProxyCredentials(String realm, Credentials cred)和 getProxyCredentials(String realm)設、取登陸信息。
3)認證方案(authentication schemes)
Basic
是HTTP中規定最先的也是最兼容(?)的方案,遺憾的是也是最不安全的一個方案,由於它以明碼傳送用戶名和密碼。它要求一個UsernamePasswordCredentials實例,能夠指定服務器端的訪問空間或採用默認的登陸信息。
Digest
是在HTTP1.1中增長的一個方案,雖然不如Basic獲得的軟件支持多,但仍是有普遍的使用。Digest方案比Basic方案安全得多,因它根本就不經過網絡傳送實際的密碼,傳送的是利用這個密碼對從服務器傳來的一個隨機數(nonce)的加密串。它要求一個UsernamePasswordCredentials實例,能夠指定服務器端的訪問空間或採用默認的登陸信息。
NTLM
這是HttpClient支持的最複雜的認證協議。它M$設計的一個私有協議,沒有公開的規範說明。一開始因爲設計的缺陷,NTLM的安全性比Digest差,後來通過一個ServicePack補丁後,安全性則比較Digest高。NTLM須要一個NTCredentials實例. 注意,因爲NTLM不使用訪問空間(realms)的概念,HttpClient利用服務器的域名做訪問空間的名字。還須要注意,提供給NTCredentials的用戶名,不要用域名的前綴 - 如: "adrian" 是正確的,而 "DOMAIN\adrian" 則是錯的.
NTLM認證的工做機制與basic和digest有很大的差異。這些差異通常由HttpClient處理,但理解這些差異有助避免在使用NTLM認證時出現錯誤。
- 從HttpClientAPI的角度來看,NTLM與其它認證方式同樣的工做,差異是須要提供'NTCredentials'實例而不是'UsernamePasswordCredentials'(其實,前者只是擴展了後者)
- 對NTLM認證,訪問空間是鏈接到的機器的域名,這對多域名主機會有一些麻煩.只有HttpClient鏈接中指定的域名纔是認證用的域名。建議將realm設爲null以使用默認的設置。
- NTLM只是認證了一個鏈接而不是一請求,因此每當一個新的鏈接創建就要進行一次認證,且在認證的過程當中保持鏈接是很是重要的。 所以,NTLM不能同時用於代理認證和服務器認證,也不能用於http1.0鏈接或服務器不支持持久鏈接的狀況。
二、重定向
因爲技術限制,以及爲保證2.0發佈版API的穩定,HttpClient還不能自動處重定向,但對重定向到同一主機、同一端口且採用同一協議的狀況HttpClient能夠支持。不能自動的處理的狀況,包括須要人工交互的狀況,或超出httpclient的能力。
當服務器重定向指令指到不一樣的主機時,HttpClient只是簡單地將重定向狀態碼做爲應答狀態。全部的300到399(包含兩端)的返回碼,都表示是重定向應答。常見的有:
- 301 永久移動. HttpStatus.SC_MOVED_PERMANENTLY
- 302 臨時移動. HttpStatus.SC_MOVED_TEMPORARILY
- 303 See Other. HttpStatus.SC_SEE_OTHER
- 307 臨時重定向. HttpStatus.SC_TEMPORARY_REDIRECT
當收到簡單的重定向時,程序應從HttpMethod對象中抽取新的URL並將其下載。另外,限制一下重定向次數是個好的主意,這能夠避免遞歸循環。新的URL能夠從頭字段Location中抽取,以下:
String redirectLocation;
Header locationHeader = method.getResponseHeader("location");
if (locationHeader != null) {
redirectLocation = locationHeader.getValue();
} else {
// The response is invalid and did not provide the new location for
// the resource. Report an error or possibly handle the response
// like a 404 Not Found error.
}
特殊重定向:
- 300 多重選擇. HttpStatus.SC_MULTIPLE_CHOICES
- 304 沒有改動. HttpStatus.SC_NO T_MODIFIED
- 305 使用代理. HttpStatus.SC_USE_PROXY