<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    posts - 19, comments - 53, trackbacks - 0, articles - 283
      BlogJava :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理

    HttpClient 一文通 (摘)

    Posted on 2010-01-14 23:08 Gavin.lee 閱讀(771) 評(píng)論(0)  編輯  收藏 所屬分類: java SE & EE

    原文出處--------http://hi.baidu.com/wader2006/blog/item/7e7b3a291f7801fd99250a91.html  

    雖然用telnet這樣的程序都可把頁面取回來,但是在與web服務(wù)器的交互中,如果涉及cookie或https或ssl等內(nèi)容,一般功能相對(duì)完備的http客戶端還是非常必要的。IE或NetScape等瀏覽器確實(shí)不錯(cuò),可是如果為實(shí)現(xiàn)持續(xù)互動(dòng)而在程序調(diào)用瀏覽器,我個(gè)人認(rèn)為其中的工作量還是不小的,這還沒考慮版權(quá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
    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

    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. 透明地穿過HTTP代理建立連接
    5. 通過CONNECT方法,利用通過建立穿過HTTP代理的HTTPS連接
    6. 利用本地Java socket,透明地穿過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ù)器送出的應(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中沒有與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í)行方法的過程中,有兩種異常,一種是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í)例中,可以通過 setCredentials(String realm, Credentials cred)和getCredentials(String realm)來獲取或設(shè)置。注意,設(shè)定對(duì)非特定站點(diǎn)訪問所需要的登錄信息,將realm參數(shù)置為null. HttpClient內(nèi)建的自動(dòng)認(rèn)證,可以通過HttpMethod類的setDoAuthentication(boolean doAuthentication)方法關(guān)閉,而且這次關(guān)閉只影響HttpMethod當(dāng)前的實(shí)例。
      搶先認(rèn)證(Preemptive Authentication)可以通過下述方法打開.

    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ù)器端的訪問空間或采用默認(rèn)的登錄信息。
      Digest
      是在HTTP1.1中增加的一個(gè)方案,雖然不如Basic得到的軟件支持多,但還是有廣泛的使用。Digest方案比Basic方案安全得多,因它根本就不通過網(wǎng)絡(luò)傳送實(shí)際的密碼,傳送的是利用這個(gè)密碼對(duì)從服務(wù)器傳來的一個(gè)隨機(jī)數(shù)(nonce)的加密串。它要求一個(gè)UsernamePasswordCredentials實(shí)例,可以指定服務(wù)器端的訪問空間或采用默認(rèn)的登錄信息。
      NTLM
      這是HttpClient支持的最復(fù)雜的認(rèn)證協(xié)議。它M$設(shè)計(jì)的一個(gè)私有協(xié)議,沒有公開的規(guī)范說明。一開始由于設(shè)計(jì)的缺陷,NTLM的安全性比Digest差,后來經(jīng)過一個(gè)ServicePack補(bǔ)丁后,安全性則比較Digest高。NTLM需要一個(gè)NTCredentials實(shí)例. 注意,由于NTLM不使用訪問空間(realms)的概念,HttpClient利用服務(wù)器的域名作訪問空間的名字。還需要注意,提供給NTCredentials的用戶名,不要用域名的前綴 - 如: "adrian" 是正確的,而 "DOMAIN\adrian" 則是錯(cuò)的.
      NTLM認(rèn)證的工作機(jī)制與basic和digest有很大的差別。這些差別一般由HttpClient處理,但理解這些差別有助避免在使用NTLM認(rèn)證時(shí)出現(xiàn)錯(cuò)誤。

    1. 從HttpClientAPI的角度來看,NTLM與其它認(rèn)證方式一樣的工作,差別是需要提供'NTCredentials'實(shí)例而不是'UsernamePasswordCredentials'(其實(shí),前者只是擴(kuò)展了后者)
    2. 對(duì)NTLM認(rè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)證的過程中保持連接是非常重要的。 因此,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)答。常見的有:

    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.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.
    }


    特殊重定向:

    1. 300 多重選擇. HttpStatus.SC_MULTIPLE_CHOICES
    2. 304 沒有改動(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頁面等)),必須以US-ASCII編碼,這是因?yàn)轭^部不傳數(shù)據(jù)而只描述被要傳輸?shù)臄?shù)據(jù)的一些信息,一個(gè)例外是cookie,它是數(shù)據(jù)但是通過頭部進(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、Cookies


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

    1. Netscape cookie草案,是最早的cookie規(guī)范,基于rfc2109。盡管這個(gè)規(guī)范與rc2109有較大的差別,這樣做可以與一些服務(wù)器兼容。
    2. rfc2109,是w3c發(fā)布的第一個(gè)官方cookie規(guī)范。理論上講,所有的服務(wù)器在處理cookie(版本1)時(shí),都要遵循此規(guī)范,正因如此,HttpClient將其設(shè)為默認(rèn)的規(guī)范。遺憾的是,這個(gè)規(guī)范太嚴(yán)格了,以致很多服務(wù)器不正確的實(shí)施了該規(guī)范或仍在作用Netscape規(guī)范。在這種情況下,應(yīng)使用兼容規(guī)范。
    3. 兼容性規(guī)范,設(shè)計(jì)用來兼容盡可能多的服務(wù)器,即使它們并沒有遵循標(biāo)準(zhǔn)規(guī)范。當(dāng)解析cookie出現(xiàn)問題時(shí),應(yīng)考慮采用兼容性規(guī)范。


       RFC2965規(guī)范暫時(shí)沒有被HttpClient支持(在以后的版本為會(huì)加上),它定義了cookie版本2,并說明了版本1cookie的不足,RFC2965有意有久取代rfc2109.
      在HttpClient中,有兩種方法來指定cookie規(guī)范的使用,

    1. HttpClient client = new HttpClient();
      client.getState().setCookiePolicy(CookiePolicy.COMPATIBILITY);
      這種方法設(shè)置的規(guī)范只對(duì)當(dāng)前的HttpState有效,參數(shù)可取值CookiePolicy.COMPATIBILITY,CookiePolicy.NETSCAPE_DRAFT或CookiePolicy.RFC2109。
    2. System.setProperty("apache.commons.httpclient.cookiespec", "COMPATIBILITY");
      此法指的規(guī)范,對(duì)以后每個(gè)新建立的HttpState對(duì)象都有效,參數(shù)可取值"COMPATIBILITY","NETSCAPE_DRAFT"或"RFC2109"。
        常有不能解析cookie的問題,但更換到兼容規(guī)范大都能解決。

      

    9、使用HttpClient遇到問題怎么辦? 

    1. 用一個(gè)瀏覽器訪問服務(wù)器,以確認(rèn)服務(wù)器應(yīng)答正常
    2. 如果在使代理,關(guān)掉代理試試
    3. 另找一個(gè)服務(wù)器來試試(如果運(yùn)行著不同的服務(wù)器軟件更好)
    4. 檢查代碼是否按教程中講的思路編寫
    5. 設(shè)置log級(jí)別為debug,找出問題出現(xiàn)的原因
    6. 打開wiretrace,來追蹤客戶端與服務(wù)器的通信,以確實(shí)問題出現(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.   

    10、SSL


      借助Java Secure Socket Extension (JSSE),HttpClient全面支持Secure Sockets Layer (SSL)或IETF Transport Layer Security (TLS)協(xié)議上的HTTP。JSSE已經(jīng)jre1.4及以后的版本中,以前的版本則需要手工安裝設(shè)置,具體過程參見Sun網(wǎng)站或本學(xué)習(xí)筆記。
      HttpClient中使用SSL非常簡(jiǎn)單,參考下面兩個(gè)例子:

    HttpClient httpclient = new HttpClient();
    GetMethod httpget = new GetMethod("https://www.verisign.com/");
    httpclient.executeMethod(httpget);
    System.out.println(httpget.getStatusLine().toString());

    ,如果通過需要授權(quán)的代理,則如下:

    HttpClient httpclient = new HttpClient();
    httpclient.getHostConfiguration().setProxy("myproxyhost", 8080);
    httpclient.getState().setProxyCredentials("my-proxy-realm", " myproxyhost",
    new UsernamePasswordCredentials("my-proxy-username", "my-proxy-password"));
    GetMethod httpget = new GetMethod("https://www.verisign.com/");
    httpclient.executeMethod(httpget);
    System.out.println(httpget.getStatusLine().toString());


      在HttpClient中定制SSL的步驟如下:

    1. 提供了一個(gè)實(shí)現(xiàn)了org.apache.commons.httpclient.protocol.SecureProtocolSocketFactory接口的socket factory。這個(gè) socket factory負(fù)責(zé)打一個(gè)到服務(wù)器的端口,使用標(biāo)準(zhǔn)的或第三方的SSL函數(shù)庫(kù),并進(jìn)行象連接握手等初始化操作。通常情況下,這個(gè)初始化操作在端口被創(chuàng)建時(shí)自動(dòng)進(jìn)行的。
    2. 實(shí)例化一個(gè)org.apache.commons.httpclient.protocol.Protocol對(duì)象。創(chuàng)建這個(gè)實(shí)例時(shí),需要一個(gè)合法的協(xié)議類型(如https),一個(gè)定制的socket factory,和一個(gè)默認(rèn)的端中號(hào)(如https的443端口).
      Protocol myhttps = new Protocol("https", new MySSLSocketFactory(), 443);
      然后,這個(gè)實(shí)例可被設(shè)置為協(xié)議的處理器。
      HttpClient httpclient = new HttpClient();
      httpclient.getHostConfiguration().setHost("www.whatever.com", 443, myhttps);
      GetMethod httpget = new GetMethod("/");
      httpclient.executeMethod(httpget);
    3. 通過調(diào)用Protocol.registerProtocol方法,將此定制的實(shí)例,注冊(cè)為某一特定協(xié)議的默認(rèn)的處理器。由此,可以很方便地定制自己的協(xié)議類型(如myhttps)。
      Protocol.registerProtocol("myhttps",
      new Protocol("https", new MySSLSocketFactory(), 9443));
      ...
      HttpClient httpclient = new HttpClient();
      GetMethod httpget = new GetMethod("myhttps://www.whatever.com/");
      httpclient.executeMethod(httpget);
      如果想用自己定制的處理器取代https默認(rèn)的處理器,只需要將其注冊(cè)為"https"即可。
      Protocol.registerProtocol("https",
      new Protocol("https", new MySSLSocketFactory(), 443));
      HttpClient httpclient = new HttpClient();
      GetMethod httpget = new GetMethod("https://www.whatever.com/");
      httpclient.executeMethod(httpget);


      已知的限制和問題

    1. 持續(xù)的SSL連接在Sun的低于1.4JVM上不能工作,這是由于JVM的bug造成。
    2. 通過代理訪問服務(wù)器時(shí),非搶先認(rèn)證( Non-preemptive authentication)會(huì)失敗,這是由于HttpClient的設(shè)計(jì)缺陷造成的,以后的版本中會(huì)修改。


      遇到問題的處理
      很多問題,特別是在jvm低于1.4時(shí),是由jsse的安裝造成的。
      下面的代碼,可作為最終的檢測(cè)手段。

    import java.io.BufferedReader;
    import java.io.InputStreamReader;
    import java.io.OutputStreamWriter;
    import java.io.Writer;
    import java.net.Socket; import javax.net.ssl.SSLSocketFactory; public class Test {

    public static final String TARGET_HTTPS_SERVER = "www.verisign.com";
    public static final int TARGET_HTTPS_PORT = 443;

    public static void main(String[] args) throws Exception {

    Socket socket = SSLSocketFactory.getDefault().
    createSocket(TARGET_HTTPS_SERVER, TARGET_HTTPS_PORT);
    try {
    Writer out = new OutputStreamWriter(
    socket.getOutputStream(), "ISO-8859-1");
    out.write("GET / HTTP/1.1\r\n");
    out.write("Host: " + TARGET_HTTPS_SERVER + ":" +
    TARGET_HTTPS_PORT + "\r\n");
    out.write("Agent: SSL-TEST\r\n");
    out.write("\r\n");
    out.flush();
    BufferedReader in = new BufferedReader(
    new InputStreamReader(socket.getInputStream(), "ISO-8859-1"));
    String line = null;
    while ((line = in.readLine()) != null) {
    System.out.println(line);
    }
    } finally {
    socket.close();
    }
    }
    }

    1、httpclient的多線程處理


      使用多線程的主要目的,是為了實(shí)現(xiàn)并行的下載。在httpclient運(yùn)行的過程中,每個(gè)http協(xié)議的方法,使用一個(gè)HttpConnection實(shí)例。由于連接是一種有限的資源,每個(gè)連接在某一時(shí)刻只能供一個(gè)線程和方法使用,所以需要確保在需要時(shí)正確地分配連接。HttpClient采用了一種類似jdbc連接池的方法來管理連接,這個(gè)管理工作由 MultiThreadedHttpConnectionManager完成。

    MultiThreadedHttpConnectionManager connectionManager =
    new MultiThreadedHttpConnectionManager();
    HttpClient client = new HttpClient(connectionManager);

    此是,client可以在多個(gè)線程中被用來執(zhí)行多個(gè)方法。每次調(diào)用HttpClient.executeMethod() 方法,都會(huì)去鏈接管理器申請(qǐng)一個(gè)連接實(shí)例,申請(qǐng)成功這個(gè)鏈接實(shí)例被簽出(checkout),隨之在鏈接使用完后必須歸還管理器。管理器支持兩個(gè)設(shè)置:

    maxConnectionsPerHost 每個(gè)主機(jī)的最大并行鏈接數(shù),默認(rèn)為2
    maxTotalConnections 客戶端總并行鏈接最大數(shù),默認(rèn)為20

      管理器重新利用鏈接時(shí),采取早歸還者先重用的方式(least recently used approach)。
      由于是使用HttpClient的程序而不是HttpClient本身來讀取應(yīng)答包的主體,所以HttpClient無法決定什么時(shí)間連接不再使用了,這也就要求在讀完應(yīng)答包的主體后必須手工顯式地調(diào)用releaseConnection()來釋放申請(qǐng)的鏈接。

    MultiThreadedHttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager();
    HttpClient client = new HttpClient(connectionManager);
    ...
    // 在某個(gè)線程中。
    GetMethod get = new GetMethod("http://jakarta.apache.org/");
    try {
    client.executeMethod(get);
    // print response to stdout
    System.out.println(get.getResponseBodyAsStream());
    } finally {
    // be sure the connection is released back to the connection
    // manager
    get.releaseConnection();
    }

    對(duì)每一個(gè)HttpClient.executeMethod須有一個(gè)method.releaseConnection()與之匹配.

    12、HTTP方法


      HttpClient支持的HTTP方法有8種,下面分述之。

      1、Options

      HTTP方法Options用來向服務(wù)器發(fā)送請(qǐng)求,希望獲得針對(duì)由請(qǐng)求URL(request url)標(biāo)志的資源在請(qǐng)求/應(yīng)答的通信過程可以使用的功能選項(xiàng)。通過這個(gè)方法,客戶端可以在采取具體行動(dòng)之前,就可對(duì)某一資源決定采取什么動(dòng)作和/或以及一些必要條件,或者了解服務(wù)器提供的功能。這個(gè)方法最典型的應(yīng)用,就是用來獲取服務(wù)器支持哪些HTTP方法。
      HttpClient中有一個(gè)類叫OptionsMethod,來支持這個(gè)HTTP方法,利用這個(gè)類的getAllowedMethods方法,就可以很簡(jiǎn)單地實(shí)現(xiàn)上述的典型應(yīng)用。

    OptionsMethod options = new OptionsMethod("http://jakarta.apache.org");
    // 執(zhí)行方法并做相應(yīng)的異常處理
    ...
    Enumeration allowedMethods = options.getAllowedMethods();
    options.releaseConnection();


      2、Get

       HTTP方法GET用來取回請(qǐng)求URI(request-URI)標(biāo)志的任何信息(以實(shí)體(entity)的形式),"get"這個(gè)單詞本意就是”獲取“的意思。如果請(qǐng)求URI指向的一個(gè)數(shù)據(jù)處理過程,那這個(gè)過程生成的數(shù)據(jù),在應(yīng)答中以實(shí)體的形式被返回,而不是將這個(gè)過程的代碼的返回。
      如果HTTP包中含有If-ModifiedSince, If-Unmodified-Since, If-Match, If-None-Match, 或 If-Range等頭字段,則GET也就變成了”條件GET“,即只有滿足上述字段描述的條件的實(shí)體才被取回,這樣可以減少一些非必需的網(wǎng)絡(luò)傳輸,或者減少為獲取某一資源的多次請(qǐng)求(如第一次檢查,第二次下載)。(一般的瀏覽器,都有一個(gè)臨時(shí)目錄,用來緩存一些網(wǎng)頁信息,當(dāng)再次瀏覽某個(gè)頁面的時(shí)候,只下載那些修改過的內(nèi)容,以加快瀏覽速度,就是這個(gè)道理。至于檢查,則常用比GET更好的方法HEAD來實(shí)現(xiàn)。)如果HTTP包中含有Range頭字段,那么請(qǐng)求URI指定的實(shí)體中,只有決定范圍條件的那部分才被取回來。(用過多線程下載工具的朋友,可能比較容易理解這一點(diǎn))
      這個(gè)方法的典型應(yīng)用,用來從web服務(wù)器下載文檔。HttpClient定義了一個(gè)類叫GetMethod來支持這個(gè)方法,用GetMethod類中g(shù)etResponseBody, getResponseBodyAsStream 或 getResponseBodyAsString函數(shù)就可以取到應(yīng)答包包體中的文檔(如HTML頁面)信息。這這三個(gè)函數(shù)中,getResponseBodyAsStream通常是最好的方法,主要是因?yàn)樗梢员苊庠谔幚硐螺d的文檔之前緩存所有的下載的數(shù)據(jù)。

    GetMethod get = new GetMethod("http://jakarta.apache.org");
    // 執(zhí)行方法,并處理失敗的請(qǐng)求.
    ...
    InputStream in = get.getResponseBodyAsStream();
    // 利用輸入流來處理信息。
    get.releaseConnection();


      對(duì)GetMethod的最常見的不正確的使用,是沒有將全部的應(yīng)答主體的數(shù)據(jù)讀出來。還有,必須注意要手工明確地將鏈接釋放。

      3、Head

      HTTP的Head方法,與Get方法完全一致,唯一的差別是服務(wù)器不能在應(yīng)答包中包含主體(message-body),而且一定不能包含主體。使用這個(gè)方法,可以使得客戶無需將資源下載回就可就以得到一些關(guān)于它的基本信息。這個(gè)方法常用來檢查超鏈的可訪問性以及資源最近有沒有被修改。
      HTTP的head方法最典型的應(yīng)用,是獲取資源的基本信息。HttpClient定義了HeadMethod類支持這個(gè)方法,HeadMethod類與其它*Method類一樣,用 getResponseHeaders()取回頭部信息,而沒有自己的特殊方法。

    HeadMethod head = new HeadMethod("http://jakarta.apache.org");
    // 執(zhí)行方法,并處理失敗的請(qǐng)求.
    ...
    // 取回應(yīng)答包的頭字段信息.
    Header[] headers = head.getResponseHeaders(); // 只取回最后修改日期字段的信息.
    String lastModified = head.getResponseHeader("last-modified").getValue();



      4、Post

      Post在英文有“派駐”的意思,HTTP方法POST就是要求服務(wù)器接受請(qǐng)求包中的實(shí)體,并將其作為請(qǐng)求URI的下屬資源。從本質(zhì)上說,這意味著服務(wù)器要保存這個(gè)實(shí)體信息,而且通常由服務(wù)器端的程序進(jìn)行處理。Post方法的設(shè)計(jì)意圖,是要以一種統(tǒng)一的方式實(shí)現(xiàn)下列功能:

    1. 對(duì)已有的資源做評(píng)注
    2. 將信息發(fā)布到BBS、新聞組、郵件列表,或類似的文章組中
    3. 將一塊數(shù)據(jù),提交給數(shù)據(jù)處理進(jìn)程
    4. 通過追加操作,來擴(kuò)展一個(gè)數(shù)據(jù)庫(kù)

      這些都操作期待著在服務(wù)器端產(chǎn)生一定的“副作用”,如修改了數(shù)據(jù)庫(kù)等。
      HttpClient定義PostMethod類以支持該HTTP方法,在httpclient中,使用post方法有兩個(gè)基本的步驟:為請(qǐng)求包準(zhǔn)備數(shù)據(jù),然后讀取服務(wù)器來的應(yīng)答包的信息。通過調(diào)用 setRequestBody()函數(shù),來為請(qǐng)求包提供數(shù)據(jù),它可以接收三類參數(shù):輸入流、名值對(duì)數(shù)組或字符串。至于讀取應(yīng)答包需要調(diào)用 getResponseBody* 那一系列的方法,與GET方法處理應(yīng)答包的方法相同。
      常見問題是,沒有將全部應(yīng)答讀取(無論它對(duì)程序是否有用),或沒有釋放鏈接資源。

    主站蜘蛛池模板: 成人黄页网站免费观看大全| 永久免费无码网站在线观看个| 亚洲视频在线不卡| 亚洲成a人片77777老司机| 久久久久久久亚洲精品| 亚洲综合精品网站在线观看| 亚洲第一区精品观看| 免费国产成人高清视频网站| 亚洲 无码 在线 专区| 亚洲 综合 国产 欧洲 丝袜 | 在线视频亚洲一区| 亚洲色一区二区三区四区| 亚洲熟妇无码AV不卡在线播放| 一本色道久久88亚洲精品综合| 亚洲最大无码中文字幕| 亚洲变态另类一区二区三区| 国产精品亚洲小说专区| 牛牛在线精品观看免费正| caoporm超免费公开视频| 日韩a级无码免费视频| 99国产精品免费视频观看| 中文字幕在线免费| 皇色在线视频免费网站| 日韩午夜免费视频| 全黄a免费一级毛片人人爱| 亚洲国产成人久久综合碰| 亚洲码国产精品高潮在线| 337p日本欧洲亚洲大胆色噜噜| 亚洲依依成人精品| 亚洲av无码成人精品区一本二本| 一级毛片免费在线| 无人在线观看免费高清| 亚洲人成网站免费播放| 四虎永久精品免费观看| 亚洲精品成人片在线观看精品字幕 | 国产免费网站看v片在线| 114级毛片免费观看| 国内自产拍自a免费毛片| 免费国产成人午夜电影| 国产aⅴ无码专区亚洲av| 亚洲国产精品综合久久久|