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

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

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

    Terry.Li-彬

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

      BlogJava :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
      143 隨筆 :: 344 文章 :: 130 評論 :: 0 Trackbacks

    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非常簡單,參考下面兩個(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ù)庫,并進(jìn)行象連接握手等初始化操作。通常情況下,這個(gè)初始化操作在端口被創(chuàng)建時(shí) 自動進(jìn)行的。

    2. 實(shí)例化一個(gè)org.apache.commons.httpclient.protocol.Protocol對象。創(chuàng)建這個(gè)實(shí)例時(shí),需要一個(gè)合法的協(xié)議類型(如https),一個(gè)定制的socket factory,和一個(gè)默認(rèn)的端中號(如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í)例,注冊為某一特定協(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)的處理器,只需要將其注冊為"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)會失敗,這是由于HttpClient的設(shè)計(jì)缺陷造成的,以后的版本中會修改。

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

    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();
    }
    }
    }


    11、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() 方法,都會去鏈接管理器申請一個(gè)連接實(shí)例,申請成功這個(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()來釋放申請的鏈接。
    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();
    }
    對每一個(gè)HttpClient.executeMethod須有一個(gè)method.releaseConnection()與之匹配.

    12、HTTP方法


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

    1、Options

    HTTP方法Options用來向服務(wù)器發(fā)送請求,希望獲得針對由請求URL(request url)標(biāo)志的資源在請求/應(yīng)答的通信過程可以使用的功能選項(xiàng)。通過這個(gè)方法,客戶端可以在采取具體行動之前,就可對某一資源決定采取什么動作和/或以及 一些必要條件,或者了解服務(wù)器提供的功能。這個(gè)方法最典型的應(yīng)用,就是用來獲取服務(wù)器支持哪些HTTP方法。
    HttpClient中有一個(gè)類叫OptionsMethod,來支持這個(gè)HTTP方法,利用這個(gè)類的getAllowedMethods方法,就可以很簡單地實(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用來取回請求URI(request-URI)標(biāo)志的任何信息(以實(shí)體(entity)的形式),"get"這個(gè)單詞本意就是”獲取 “的意思。如果請求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ò)傳輸,或者減 少為獲取某一資源的多次請求(如第一次檢查,第二次下載)。(一般的瀏覽器,都有一個(gè)臨時(shí)目錄,用來緩存一些網(wǎng)頁信息,當(dāng)再次瀏覽某個(gè)頁面的時(shí)候,只下載 那些修改過的內(nèi)容,以加快瀏覽速度,就是這個(gè)道理。至于檢查,則常用比GET更好的方法HEAD來實(shí)現(xiàn)。)如果HTTP包中含有Range頭字段,那么請 求URI指定的實(shí)體中,只有決定范圍條件的那部分才被取回來。(用過多線程下載工具的朋友,可能比較容易理解這一點(diǎn))
    這個(gè)方法的典型應(yīng)用,用 來從web服務(wù)器下載文檔。HttpClient定義了一個(gè)類叫GetMethod來支持這個(gè)方法,用GetMethod類中 getResponseBody, getResponseBodyAsStream 或 getResponseBodyAsString函數(shù)就可以取到應(yīng)答包包體中的文檔(如HTML頁面)信息。這這三個(gè)函數(shù)中, getResponseBodyAsStream通常是最好的方法,主要是因?yàn)樗梢员苊庠谔幚硐螺d的文檔之前緩存所有的下載的數(shù)據(jù)。

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

    對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í)行方法,并處理失敗的請求.
    ...
    // 取回應(yīng)答包的頭字段信息.
    Header[] headers = head.getResponseHeaders(); // 只取回最后修改日期字段的信息.
    String lastModified = head.getResponseHeader("last-modified").get();


    4、Post

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

    2. 將信息發(fā)布到BBS、新聞組、郵件列表,或類似的文章組中

    3. 將一塊數(shù)據(jù),提交給數(shù)據(jù)處理進(jìn)程

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

    參考資料:

    http://www.systinet.com/doc/wasp_uddi/uddi/igpreliminary.html
    posted on 2008-02-13 22:32 禮物 閱讀(1080) 評論(0)  編輯  收藏 所屬分類: Jakarta
    主站蜘蛛池模板: 亚洲国产综合精品中文字幕| 亚洲av永久无码天堂网| 国产亚洲福利一区二区免费看| 国产自国产自愉自愉免费24区| 亚洲成熟丰满熟妇高潮XXXXX| 久久久无码精品亚洲日韩蜜臀浪潮| 亚洲精品和日本精品| 在线观看免费大黄网站| 色播精品免费小视频| 性xxxx视频免费播放直播| 不卡视频免费在线观看| 特级毛片A级毛片免费播放| 国产亚洲精品影视在线| 久久水蜜桃亚洲av无码精品麻豆| 国产精品亚洲片在线观看不卡| 亚洲日韩精品无码专区网站| 在线免费观看国产视频| 我要看WWW免费看插插视频| 亚洲电影免费观看| 国产2021精品视频免费播放| 日本在线看片免费| 久久精品国产免费一区| 女人隐私秘视频黄www免费| 国产免费一区二区三区免费视频 | 日本免费电影一区二区| 国产精品福利片免费看| 国产成人无码精品久久久免费| 成人午夜影视全部免费看| 特级aaaaaaaaa毛片免费视频| 午夜亚洲WWW湿好爽| 亚洲AV成人无码久久WWW| 亚洲heyzo专区无码综合| 亚洲国产一区二区三区在线观看| 亚洲宅男精品一区在线观看| 亚洲1区1区3区4区产品乱码芒果| 亚洲乱人伦精品图片| 亚洲人成7777| 九九精品国产亚洲AV日韩| 美女被暴羞羞免费视频| 亚洲精品视频免费| a级毛片黄免费a级毛片|