Terry.Li-彬

          虛其心,可解天下之問(wèn);專其心,可治天下之學(xué);靜其心,可悟天下之理;恒其心,可成天下之業(yè)。

            BlogJava :: 首頁(yè) :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
            143 隨筆 :: 344 文章 :: 130 評(píng)論 :: 0 Trackbacks
          雖然用telnet這樣的程序都可把頁(yè)面取回來(lái),但是在與web服務(wù)器的交互中,如果涉及或https或ssl等內(nèi)容,一般功能相對(duì)完備的http客戶端 還是非常必要的。IE或NetScape等瀏覽器確實(shí)不錯(cuò),可是如果為實(shí)現(xiàn)持續(xù)互動(dòng)而在程序調(diào)用瀏覽器,我個(gè)人認(rèn)為其中的工作量還是不小的,這還沒(méi)考慮版 權(quán)問(wèn)題。最好的辦法,就是能有一個(gè)開源的包,能實(shí)現(xiàn)http客戶端的功能,供我們開發(fā)的程序調(diào)用。httpclient就是這么一個(gè)包,我相信可能有比它的實(shí)現(xiàn)更好的,但目前我只關(guān)注這個(gè)。:)
          下面是nogoop做的功能比較表:

          Features nogoop Sun JRE < 1.4.2 Sun JRE 1.4.2 Innovation Apache/Jakarta
          s


          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

          1、HttpClient的功能

          1. 基于標(biāo)準(zhǔn),純正java,實(shí)現(xiàn)了http1.0和1.1。

          2. 在一個(gè)可擴(kuò)展的OO框架內(nèi),實(shí)現(xiàn)了HTTP的全部方法(GET, POST,
            PUT, DELETE, HEAD, OPTIONS, and TRACE)

          3. 支持HTTPS(ssl上的HTTP)的加密操作

          4. 透明地穿過(guò)HTTP代理建立連接

          5. 通過(guò)CONNECT方法,利用通過(guò)建立穿過(guò)HTTP代理的HTTPS連接

          6. 利用本地Java socket,透明地穿過(guò)SOCKS(版本5和4)代理建立連接

          7. 支持利用Basic、Digest和NTLM加密的認(rèn)證

          8. 支持用于上傳大文件的Multi-Part表單POST方法

          9. 插件式安全socket實(shí)現(xiàn),易于使用第三方的解決方案

          10. 連接管理,支持多線程應(yīng)用,支持設(shè)定單個(gè)主機(jī)總連接和最高連接數(shù)量,自動(dòng)檢測(cè)和關(guān)閉失效連接

          11. 直接將請(qǐng)求信息流送到服務(wù)器的端口

          12. 直接讀取從服務(wù)器的端口送出的應(yīng)答信息

          13. 支持HTTP/1.0中用KeepAlive和HTTP/1.1中用persistance設(shè)置的持久連接

          14. 直接訪問(wèn)由服務(wù)器送出的應(yīng)答代碼和頭部信息

          15. 可設(shè)置連接超時(shí)時(shí)間

          16. HttpMethods 實(shí)現(xiàn)Command Pattern,以允許并行請(qǐng)求或高效連接復(fù)用

          17. 遵循the Apache Software License協(xié)議,源碼免費(fèi)可得

          2、預(yù)備工作


          對(duì)jre1.3.*,如果要HttpClient支持https,則需要下載并安裝jssejce.安裝的步驟如下:
          1)下載jsse和jce.
          2)檢查CLASSPATH中沒(méi)有與jsse和jce相關(guān)的jar包
          3)將 US_export_policy.jar、local_policy.jar、jsse.jar、jnet.jar、jce1_2_x.jar、sunjce_provider.jar、jcert.jar復(fù)制到目錄:
          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一塊安裝。

          3、取得源碼

          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

          4、使用HttpClient編程的基本步聚

          1. 創(chuàng)建 HttpClient 的一個(gè)實(shí)例.

          2. 創(chuàng)建某個(gè)方法(DeleteMethod,EntityEnclosingMethod,ExpectContinueMethod, GetMethod,HeadMethod,MultipartPostMethod,OptionsMethod,PostMethod, PutMethod,TraceMethod)的一個(gè)實(shí)例,一般可用要目標(biāo)URL為參數(shù)。

          3. 讓 HttpClient 執(zhí)行這個(gè)方法.

          4. 讀取應(yīng)答信息.

          5. 釋放連接.

          6. 處理應(yīng)答.

          在執(zhí)行方法的過(guò)程中,有兩種異常,一種是HttpRecoverableException,表示偶然性錯(cuò)誤發(fā)生,一般再試可能成功,另一種是IOException,嚴(yán)重錯(cuò)誤。
          這兒有這個(gè)教程中的一個(gè)例程,可以下載

          5、認(rèn)證


          HttpClient三種不同的認(rèn)證方案: Basic, Digest and NTLM. 這些方案可用于服務(wù)器或代理對(duì)客戶端的認(rèn)證,簡(jiǎn)稱服務(wù)器認(rèn)證或代理認(rèn)證。
          1)服務(wù)器認(rèn)證(Server Authentication)
          HttpClient處理服務(wù)器認(rèn)證幾乎是透明的,僅需要開發(fā)人員提供登錄信息(login credentials)。登錄信息保存在HttpState類的實(shí)例中,可以通過(guò) setCredentials(String realm, Credentials cred)和getCredentials(String realm)來(lái)獲取或設(shè)置。注意,設(shè)定對(duì)非特定站點(diǎn)訪問(wèn)所需要的登錄信息,將realm參數(shù)置為null. HttpClient內(nèi)建的自動(dòng)認(rèn)證,可以通過(guò)HttpMethod類的setDoAuthentication(boolean doAuthentication)方法關(guān)閉,而且這次關(guān)閉只影響HttpMethod當(dāng)前的實(shí)例。
          搶先認(rèn)證(Preemptive Authentication)可以通過(guò)下述方法打開.
          client.getState().setAuthenticationPreemptive(true);
          在這種模式時(shí),HttpClient會(huì)主動(dòng)將basic認(rèn)證應(yīng)答信息傳給服務(wù)器,即使在某種情況下服務(wù)器可能返回認(rèn)證失敗的應(yīng)答,這樣做主要是為了減少連接的建立。為使每個(gè)新建的 HttpState實(shí)例都實(shí)行搶先認(rèn)證,可以如下設(shè)置系統(tǒng)屬性。
          setSystemProperty(Authenticator.PREEMPTIVE_PROPERTY, "true");

          Httpclient實(shí)現(xiàn)的搶先認(rèn)證遵循rfc2617.
          2)代理認(rèn)證(proxy authentication)
          除了登錄信息需單獨(dú)存放以外,代理認(rèn)證與服務(wù)器認(rèn)證幾乎一致。用 setProxyCredentials(String realm, Credentials cred)和 getProxyCredentials(String realm)設(shè)、取登錄信息。
          3)認(rèn)證方案(authentication schemes)
          Basic
          是HTTP中規(guī)定最早的也是最兼容(?)的方案,遺憾的是也是最不安全的一個(gè)方案,因?yàn)樗悦鞔a傳送用戶名和密碼。它要求一個(gè)UsernamePasswordCredentials實(shí)例,可以指定服務(wù)器端的訪問(wèn)空間或采用默認(rèn)的登錄信息。
          Digest
          是在HTTP1.1中增加的一個(gè)方案,雖然不如Basic得到的軟件支持多,但還是有廣泛的使用。Digest方案比Basic方案安全得多,因它根本 就不通過(guò)網(wǎng)絡(luò)傳送實(shí)際的密碼,傳送的是利用這個(gè)密碼對(duì)從服務(wù)器傳來(lái)的一個(gè)隨機(jī)數(shù)(nonce)的加密串。它要求一個(gè) UsernamePasswordCredentials實(shí)例,可以指定服務(wù)器端的訪問(wèn)空間或采用默認(rèn)的登錄信息。
          NTLM
          這是 HttpClient支持的最復(fù)雜的認(rèn)證協(xié)議。它M$設(shè)計(jì)的一個(gè)私有協(xié)議,沒(méi)有公開的規(guī)范說(shuō)明。一開始由于設(shè)計(jì)的缺陷,NTLM的安全性比Digest 差,后來(lái)經(jīng)過(guò)一個(gè)ServicePack補(bǔ)丁后,安全性則比較Digest高。NTLM需要一個(gè)NTCredentials實(shí)例. 注意,由于NTLM不使用訪問(wèn)空間(realms)的概念,HttpClient利用服務(wù)器的域名作訪問(wèn)空間的名字。還需要注意,提供給 NTCredentials的用戶名,不要用域名的前綴 - 如: "adrian" 是正確的,而 "DOMAIN"adrian" 則是錯(cuò)的.
          NTLM認(rèn)證的工作機(jī)制與basic和digest有很大的差別。這些差別一般由HttpClient處理,但理解這些差別有助避免在使用NTLM認(rèn)證時(shí)出現(xiàn)錯(cuò)誤。

          1. 從HttpClientAPI的角度來(lái)看,NTLM與其它認(rèn)證方式一樣的工作,差別是需要提供'NTCredentials'實(shí)例而不是'UsernamePasswordCredentials'(其實(shí),前者只是擴(kuò)展了后者)

          2. 對(duì)NTLM認(rèn)證,訪問(wèn)空間是連接到的機(jī)器的域名,這對(duì)多域名主機(jī)會(huì)有一些麻煩.只有HttpClient連接中指定的域名才是認(rèn)證用的域名。建議將realm設(shè)為null以使用默認(rèn)的設(shè)置。

          3. NTLM只是認(rèn)證了一個(gè)連接而不是一請(qǐng)求,所以每當(dāng)一個(gè)新的連接建立就要進(jìn)行一次認(rèn)證,且在認(rèn)證的過(guò)程中保持連接是非常重要的。 因此,NTLM不能同時(shí)用于代理認(rèn)證和服務(wù)器認(rèn)證,也不能用于http1.0連接或服務(wù)器不支持持久連接的情況。

          6、重定向


          由于技術(shù)限制,以及為保證2.0發(fā)布版API的穩(wěn)定,HttpClient還不能自動(dòng)處重定向,但對(duì)重定向到同一主機(jī)、同一端口且采用同一協(xié)議的情況HttpClient可以支持。不能自動(dòng)的處理的情況,包括需要人工交互的情況,或超出httpclient的能力。
          當(dāng)服務(wù)器重定向指令指到不同的主機(jī)時(shí),HttpClient只是簡(jiǎn)單地將重定向狀態(tài)碼作為應(yīng)答狀態(tài)。所有的300到399(包含兩端)的返回碼,都表示是重定向應(yīng)答。常見(jiàn)的有:

          1. 301 永久移動(dòng). HttpStatus.SC_MOVED_PERMANENTLY

          2. 302 臨時(shí)移動(dòng). HttpStatus.SC_MOVED_TEMPORARILY

          3. 303 See Other. HttpStatus.SC_SEE_OTHER

          4. 307 臨時(shí)重定向. HttpStatus.SC_TEMPORARY_REDIRECT

          當(dāng)收到簡(jiǎn)單的重定向時(shí),程序應(yīng)從HttpMethod對(duì)象中抽取新的URL并將其下載。另外,限制一下重定向次數(shù)是個(gè)好的主意,這可以避免遞歸循環(huán)。新的URL可以從頭字段Location中抽取,如下:
          String redirectLocation;
          Header locationHeader = method.getResponseHeader("location");
          if (locationHeader != null) {
          redirectLocation = locationHeader.get();
          } 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.
          }

          特殊重定向:

          1. 300 多重選擇. HttpStatus.SC_MULTIPLE_CHOICES

          2. 304 沒(méi)有改動(dòng). HttpStatus.SC_NO T_MODIFIED

          3. 305 使用代理. HttpStatus.SC_USE_PROXY

          7、字符編碼(character encoding)


          一個(gè)HTTP協(xié)議的請(qǐng)求或應(yīng)答的頭部(在http協(xié)議中,數(shù)據(jù)包分 為兩部分,一部分是頭部,由一些名值對(duì)構(gòu)成,一部分是主體(body),是真正傳辦理的數(shù)據(jù)(如HTML頁(yè)面等)),必須以US-ASCII編碼,這是因 為頭部不傳數(shù)據(jù)而只描述被要傳輸?shù)臄?shù)據(jù)的一些信息,一個(gè)例外是,它是數(shù)據(jù)但是通過(guò)頭部進(jìn)行傳輸?shù)模运惨肬S-ASCII編碼。
          HTTP數(shù)據(jù)包的主體部分,可以用任何一種方式進(jìn)行編碼,默認(rèn)是ISO-8859-1,具體可以用頭部字段Content-Type指定。可以利用 addRequestHeader方法,設(shè)定編碼方式;用 getResponseCharSet取得編碼方式。對(duì)HTML或XML等類型的文檔,它們的本身的Content-Type也可以指定編碼方式,主要區(qū) 分兩者的作用范圍以得到正確實(shí)的解碼。
          URL的編碼標(biāo)準(zhǔn),由RFC1738指定為,只能是由可打印8位/字節(jié)的us-ascii字符組成,80-ff不是us-ascii字符,而00-1F是控制字符,這兩個(gè)區(qū)域中用的字符都須加以編碼(encoded)。

          8、s


          HttpClient能自動(dòng)管理,包括允許服務(wù)器設(shè)置并在需要的時(shí)候自動(dòng)將返回服務(wù)器,它也支持手工設(shè)置后發(fā)送到服務(wù)器端。不幸的是,對(duì)如何處理,有幾個(gè) 規(guī)范互相沖突:Netscape 草案, RFC2109, RFC2965,而且還有很大數(shù)量的軟件商的實(shí)現(xiàn)不遵循任何規(guī)范. 為了處理這種狀況,HttpClient提供了策略驅(qū)動(dòng)的管理方式。HttpClient支持的規(guī)范有:
          1. Netscape 草案,是最早的規(guī)范,基于rfc2109。盡管這個(gè)規(guī)范與rc2109有較大的差別,這樣做可以與一些服務(wù)器兼容。

          2. rfc2109, 是w3c發(fā)布的第一個(gè)官方規(guī)范。理論上講,所有的服務(wù)器在處理(版本1)時(shí),都要遵循此規(guī)范,正因如此,HttpClient將其設(shè)為默認(rèn)的規(guī)范。遺憾的 是,這個(gè)規(guī)范太嚴(yán)格了,以致很多服務(wù)器不正確的實(shí)施了該規(guī)范或仍在作用Netscape規(guī)范。在這種情況下,應(yīng)使用兼容規(guī)范。

          3. 兼容性規(guī)范,設(shè)計(jì)用來(lái)兼容盡可能多的服務(wù)器,即使它們并沒(méi)有遵循標(biāo)準(zhǔn)規(guī)范。當(dāng)解析出現(xiàn)問(wèn)題時(shí),應(yīng)考慮采用兼容性規(guī)范。

          RFC2965規(guī)范暫時(shí)沒(méi)有被HttpClient支持(在以后的版本為會(huì)加上),它定義了版本2,并說(shuō)明了版本1的不足,RFC2965有意有久取代rfc2109.
          在HttpClient中,有兩種方法來(lái)指定規(guī)范的使用,
          1. HttpClient client = new HttpClient();
            client.getState().setPolicy(Policy.COMPATIBILITY);
            這種方法設(shè)置的規(guī)范只對(duì)當(dāng)前的HttpState有效,參數(shù)可取值Policy.COMPATIBILITY,Policy.NETSCAPE_DRAFT或Policy.RFC2109。

          2. System.setProperty("apache.commons.httpclient.spec", "COMPATIBILITY");
            此法指的規(guī)范,對(duì)以后每個(gè)新建立的HttpState對(duì)象都有效,參數(shù)可取值"COMPATIBILITY","NETSCAPE_DRAFT"或"RFC2109"。
            常有不能解析的問(wèn)題,但更換到兼容規(guī)范大都能解決。

          9、使用HttpClient遇到問(wèn)題怎么辦?

          1. 用一個(gè)瀏覽器訪問(wèn)服務(wù)器,以確認(rèn)服務(wù)器應(yīng)答正常

          2. 如果在使代理,關(guān)掉代理試試

          3. 另找一個(gè)服務(wù)器來(lái)試試(如果運(yùn)行著不同的服務(wù)器軟件更好)

          4. 檢查代碼是否按教程中講的思路編寫

          5. 設(shè)置log級(jí)別為debug,找出問(wèn)題出現(xiàn)的原因

          6. 打開wiretrace,來(lái)追蹤客戶端與服務(wù)器的通信,以確實(shí)問(wèn)題出現(xiàn)在什么地方

          7. 用telnet或netcat手工將信息發(fā)送到服務(wù)器,適合于猜測(cè)已經(jīng)找到了原因而進(jìn)行試驗(yàn)時(shí)

          8. 將netcat以監(jiān)聽方式運(yùn)行,用作服務(wù)器以檢查httpclient如何處理應(yīng)答的。

          9. 利用最新的httpclient試試,bug可能在最新的版本中修復(fù)了

          10. 向郵件列表求幫助

          11. 向bugzilla報(bào)告bug.
          posted on 2008-02-13 22:23 禮物 閱讀(892) 評(píng)論(0)  編輯  收藏 所屬分類: Jakarta
          主站蜘蛛池模板: 砚山县| 萝北县| 九龙城区| 罗江县| 杭州市| 道孚县| 虞城县| 蒙山县| 扶余县| 睢宁县| 灵台县| 资中县| 汶川县| 南充市| 东丽区| 泸西县| 奉节县| 兴安县| 虞城县| 宝应县| 搜索| 乌兰县| 儋州市| 张家港市| 衡水市| 同仁县| 赫章县| 密山市| 延长县| 永和县| 贡觉县| 巨鹿县| 桐庐县| 丰顺县| 静宁县| 阿克苏市| 德安县| 萍乡市| 靖远县| 孝义市| 瑞安市|