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

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

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

    隨筆-204  評論-90  文章-8  trackbacks-0
      一般的情況下我們都是使用IE或者Navigator瀏覽器來訪問一個WEB服務器,用來瀏覽頁面查看信息或者提交一些數(shù)據(jù)等等。所訪問的這些頁面有的僅 僅是一些普通的頁面,有的需要用戶登錄后方可使用,或者需要認證以及是一些通過加密方式傳輸,例如HTTPS。目前我們使用的瀏覽器處理這些情況都不會構 成問題。不過你可能在某些時候需要通過程序來訪問這樣的一些頁面,比如從別人的網(wǎng)頁中“偷”一些數(shù)據(jù);利用某些站點提供的頁面來完成某種功能,例如說我們 想知道某個手機號碼的歸屬地而我們自己又沒有這樣的數(shù)據(jù),因此只好借助其他公司已有的網(wǎng)站來完成這個功能,這個時候我們需要向網(wǎng)頁提交手機號碼并從返回的 頁面中解析出我們想要的數(shù)據(jù)來。如果對方僅僅是一個很簡單的頁面,那我們的程序會很簡單,本文也就沒有必要大張旗鼓的在這里浪費口舌。但是考慮到一些服務 授權的問題,很多公司提供的頁面往往并不是可以通過一個簡單的URL就可以訪問的,而必須經(jīng)過注冊然后登錄后方可使用提供服務的頁面,這個時候就涉及到 COOKIE問題的處理。我們知道目前流行的動態(tài)網(wǎng)頁技術例如ASP、JSP無不是通過COOKIE來處理會話信息的。為了使我們的程序能使用別人所提供 的服務頁面,就要求程序首先登錄后再訪問服務頁面,這過程就需要自行處理cookie,想想當你用java.net.HttpURLConnection 來完成這些功能時是多么恐怖的事情?。r且這僅僅是我們所說的頑固的WEB服務器中的一個很常見的“頑固”!再有如通過HTTP來上傳文件呢?不需要頭 疼,這些問題有了“它”就很容易解決了!  

    我們不可能列舉所有可能的頑固,我們會針對幾種最常見的問題進行處理。當然了,正如前面說到 的,如果我們自己使用java.net.HttpURLConnection來搞定這些問題是很恐怖的事情,因此在開始之前我們先要介紹一下一個開放源碼 的項目,這個項目就是Apache開源組織中的httpclient,它隸屬于Jakarta的commons項目,目前的版本是2.0RC2。 commons下本來已經(jīng)有一個net的子項目,但是又把httpclient單獨提出來,可見http服務器的訪問絕非易事。

    Commons -httpclient項目就是專門設計來簡化HTTP客戶端與服務器進行各種通訊編程。通過它可以讓原來很頭疼的事情現(xiàn)在輕松的解決,例如你不再管是 HTTP或者HTTPS的通訊方式,告訴它你想使用HTTPS方式,剩下的事情交給httpclient替你完成。本文會針對我們在編寫HTTP客戶端程 序時經(jīng)常碰到的幾個問題進行分別介紹如何使用httpclient來解決它們,為了讓讀者更快的熟悉這個項目我們最開始先給出一個簡單的例子來讀取一個網(wǎng) 頁的內(nèi)容,然后循序漸進解決掉前進中的所有問題。
    1.  讀取網(wǎng)頁(HTTP/HTTPS)內(nèi)容
    下面是我們給出的一個簡單的例子用來訪問某個頁面
     
    /*
     * Created on 2003-12-14 by Liudong
     
    */


    package http.demo;
    import java.io.IOException;
    import org.apache.commons.httpclient.*;
    import org.apache.commons.httpclient.methods.*;
    /**
     * 最簡單的HTTP客戶端,用來演示通過GET或者POST方式訪問某個頁面
     * 
    @author Liudong
     
    */

    public class SimpleClient {
        
    public static void main(String[] args) throws IOException
        
    {
            HttpClient client 
    = new HttpClient();   
            
    //設置代理服務器地址和端口     
         
    //client.getHostConfiguration().setProxy("proxy_host_addr",proxy_port);
            
    //使用GET方法,如果服務器需要通過HTTPS連接,那只需要將下面URL中的http換成https
            HttpMethod method = new GetMethod("http://java.sun.com";); 
            
    //使用POST方法
         
    //HttpMethod method = new PostMethod("http://java.sun.com";); 
            client.executeMethod(method);
            
    //打印服務器返回的狀態(tài)
         System.out.println(method.getStatusLine());
           
    //打印返回的信息
         System.out.println(method.getResponseBodyAsString());
           
    //釋放連接
         method.releaseConnection();
        }

    }
     
    在 這個例子中首先創(chuàng)建一個HTTP客戶端(HttpClient)的實例,然后選擇提交的方法是GET或者POST,最后在HttpClient實例上執(zhí)行 提交的方法,最后從所選擇的提交方法中讀取服務器反饋回來的結果。這就是使用HttpClient的基本流程。其實用一行代碼也就可以搞定整個請求的過 程,非常的簡單!

    2.  以GET或者POST方式向網(wǎng)頁提交參數(shù)
    其實前面一個最簡單的示例中我們已經(jīng)介紹了如何使用GET或者 POST方式來請求一個頁面,本小節(jié)與之不同的是多了提交時設定頁面所需的參數(shù),我們知道如果是GET的請求方式,那么所有參數(shù)都直接放到頁面的URL后 面用問號與頁面地址隔開,每個參數(shù)用&隔開,例如:http://java.sun.com?name=liudong&mobile=123456,但是當使用POST方法時就會稍微有一點點麻煩。本小節(jié)的例子演示向如何查詢手機號碼所在的城市,代碼如下:
    /*
     * Created on 2003-12-7 by Liudong
     
    */

    package http.demo;
    import java.io.IOException;
    import org.apache.commons.httpclient.*;
    import org.apache.commons.httpclient.methods.*;
    /**
     * 提交參數(shù)演示
     * 該程序連接到一個用于查詢手機號碼所屬地的頁面
     * 以便查詢號碼段1330227所在的省份以及城市
     * 
    @author Liudong
     
    */


    public class SimpleHttpClient {
        
    public static void main(String[] args) throws IOException
        
    {
            HttpClient client 
    = new HttpClient();
            client.getHostConfiguration().setHost(
    "www.imobile.com.cn"80"http");
            HttpMethod method 
    = getPostMethod();//使用POST方式提交數(shù)據(jù)
         client.executeMethod(method);
           
    //打印服務器返回的狀態(tài)
         System.out.println(method.getStatusLine());
           
    //打印結果頁面
        String response =   new String(method.getResponseBodyAsString().getBytes("8859_1"));
           
    //打印返回的信息
         System.out.println(response);
            method.releaseConnection();
        }

        
    /**
         * 使用GET方式提交數(shù)據(jù)
       * 
    @return
         
    */

        
    private static HttpMethod getGetMethod(){
            
    return new GetMethod("/simcard.php?simcard=1330227");
        }

        
    /**
         * 使用POST方式提交數(shù)據(jù)
       * 
    @return
         
    */

        
    private static HttpMethod getPostMethod(){
            PostMethod post 
    = new PostMethod("/simcard.php");
            NameValuePair simcard 
    = new NameValuePair("simcard","1330227");
            post.setRequestBody(
    new NameValuePair[] { simcard});
            
    return post;
        }

    }
     
    在上面的例子中頁面http://www.imobile.com.cn/simcard.php需要一個參數(shù)是simcard,這個參數(shù)值為手機號碼段,即手機號碼的前七位,服務器會返回提交的手機號碼對應的省份、城市以及其他詳細信息。GET的提交方法只需要在URL后加入?yún)?shù)信息,而POST則需要通過NameValuePair類來設置參數(shù)名稱和它所對應的值

    3.  處理頁面重定向

    在JSP/Servlet 編程中response.sendRedirect方法就是使用HTTP協(xié)議中的重定向機制。它與JSP中的<jsp:forward  …>的區(qū)別在于后者是在服務器中實現(xiàn)頁面的跳轉,也就是說應用容器加載了所要跳轉的頁面的內(nèi)容并返回給客戶端;而前者是返回一個狀態(tài)碼,這些狀態(tài) 碼的可能值見下表,然后客戶端讀取需要跳轉到的頁面的URL并重新加載新的頁面。就是這樣一個過程,所以我們編程的時候就要通過 HttpMethod.getStatusCode()方法判斷返回值是否為下表中的某個值來判斷是否需要跳轉。如果已經(jīng)確認需要進行頁面跳轉了,那么可 以通過讀取HTTP頭中的location屬性來獲取新的地址。

    狀態(tài)碼
     對應HttpServletResponse的常量
     詳細描述
     
    301
     SC_MOVED_PERMANENTLY
     頁面已經(jīng)永久移到另外一個新地址
     
    302
     SC_MOVED_TEMPORARILY
     頁面暫時移動到另外一個新的地址
     
    303
     SC_SEE_OTHER
     客戶端請求的地址必須通過另外的URL來訪問
     
    307
     SC_TEMPORARY_REDIRECT
     同SC_MOVED_TEMPORARILY


    下面的代碼片段演示如何處理頁面的重定向
    client.executeMethod(post);
            System.out.println(post.getStatusLine().toString()); 
            post.releaseConnection();
            
    //檢查是否重定向
         int statuscode = post.getStatusCode();
            
    if ((statuscode == HttpStatus.SC_MOVED_TEMPORARILY) ||
                (statuscode 
    == HttpStatus.SC_MOVED_PERMANENTLY) ||
                (statuscode 
    == HttpStatus.SC_SEE_OTHER) ||
                (statuscode 
    == HttpStatus.SC_TEMPORARY_REDIRECT)) 
            
    {//讀取新的URL地址
             Header header = post.getResponseHeader("location");
                  
    if (header != null{
                     String newuri 
    = header.getValue();
                     
    if ((newuri == null|| (newuri.equals("")))
                          newuri 
    = "/"
                   GetMethod redirect 
    = new GetMethod(newuri);
                   client.executeMethod(redirect);
                    System.out.println(
    "Redirect:"+ redirect.getStatusLine().toString()); 
                    redirect.releaseConnection();
                }
     else {
                   System.out.println(
    "Invalid redirect");
            }
     
    我們可以自行編寫兩個JSP頁面,其中一個頁面用response.sendRedirect方法重定向到另外一個頁面用來測試上面的例子。

    4.  模擬輸入用戶名和口令進行登錄

    本 小節(jié)應該說是HTTP客戶端編程中最常碰見的問題,很多網(wǎng)站的內(nèi)容都只是對注冊用戶可見的,這種情況下就必須要求使用正確的用戶名和口令登錄成功后,方可 瀏覽到想要的頁面。因為HTTP協(xié)議是無狀態(tài)的,也就是連接的有效期只限于當前請求,請求內(nèi)容結束后連接就關閉了。在這種情況下為了保存用戶的登錄信息必 須使用到Cookie機制。以JSP/Servlet為例,當瀏覽器請求一個JSP或者是Servlet的頁面時,應用服務器會返回一個參數(shù),名為 jsessionid(因不同應用服務器而異),值是一個較長的唯一字符串的Cookie,這個字符串值也就是當前訪問該站點的會話標識。瀏覽器在每訪問 該站點的其他頁面時候都要帶上jsessionid這樣的Cookie信息,應用服務器根據(jù)讀取這個會話標識來獲取對應的會話信息。

    對于 需要用戶登錄的網(wǎng)站,一般在用戶登錄成功后會將用戶資料保存在服務器的會話中,這樣當訪問到其他的頁面時候,應用服務器根據(jù)瀏覽器送上的Cookie中讀 取當前請求對應的會話標識以獲得對應的會話信息,然后就可以判斷用戶資料是否存在于會話信息中,如果存在則允許訪問頁面,否則跳轉到登錄頁面中要求用戶輸 入帳號和口令進行登錄。這就是一般使用JSP開發(fā)網(wǎng)站在處理用戶登錄的比較通用的方法。

    這樣一來,對于HTTP的客戶端來講,如果要訪問 一個受保護的頁面時就必須模擬瀏覽器所做的工作,首先就是請求登錄頁面,然后讀取Cookie值;再次請求登錄頁面并加入登錄頁所需的每個參數(shù);最后就是 請求最終所需的頁面。當然在除第一次請求外其他的請求都需要附帶上Cookie信息以便服務器能判斷當前請求是否已經(jīng)通過驗證。說了這么多,可是如果你使 用httpclient的話,你甚至連一行代碼都無需增加,你只需要先傳遞登錄信息執(zhí)行登錄過程,然后直接訪問想要的頁面,跟訪問一個普通的頁面沒有任何 區(qū)別,因為類HttpClient已經(jīng)幫你做了所有該做的事情了,太棒了!下面的例子實現(xiàn)了這樣一個訪問的過程。
    /*
     * Created on 2003-12-7 by Liudong
     
    */

    package http.demo;
    import org.apache.commons.httpclient.*;
    import org.apache.commons.httpclient.cookie.*;
    import org.apache.commons.httpclient.methods.*;
    /**
     * 用來演示登錄表單的示例
     * 
    @author Liudong
     
    */

    public class FormLoginDemo {
        
    static final String LOGON_SITE = "localhost";
        
    static final int    LOGON_PORT = 8080;
        
    public static void main(String[] args) throws Exception{
            HttpClient client 
    = new HttpClient();
            client.getHostConfiguration().setHost(LOGON_SITE, LOGON_PORT);
            
    //模擬登錄頁面login.jsp->main.jsp
            PostMethod post = new PostMethod("/main.jsp");
            NameValuePair name 
    = new NameValuePair("name""ld");     
            NameValuePair pass 
    = new NameValuePair("password""ld");     
            post.setRequestBody(
    new NameValuePair[]{name,pass});
           
    int status = client.executeMethod(post);
           System.out.println(post.getResponseBodyAsString());
           post.releaseConnection();  
           
    //查看cookie信息
        CookieSpec cookiespec = CookiePolicy.getDefaultSpec();
          Cookie[] cookies 
    = cookiespec.match(LOGON_SITE, LOGON_PORT, "/"false, client.getState().getCookies());
           
    if (cookies.length == 0{
               System.out.println(
    "None");    
           }
     else {
               
    for (int i = 0; i < cookies.length; i++{
                  System.out.println(cookies[i].toString());    
               }

          }

           
    //訪問所需的頁面main2.jsp
            GetMethod get = new GetMethod("/main2.jsp");
            client.executeMethod(get);
            System.out.println(get.getResponseBodyAsString());
            get.releaseConnection();
        }

    }
     
    5.  提交XML格式參數(shù)

    提交XML格式的參數(shù)很簡單,僅僅是一個提交時候的ContentType問題,下面的例子演示從文件文件中讀取XML信息并提交給服務器的過程,該過程可以用來測試Web服務。
    import java.io.File;
    import java.io.FileInputStream;
    import org.apache.commons.httpclient.HttpClient;
    import org.apache.commons.httpclient.methods.EntityEnclosingMethod;
    import org.apache.commons.httpclient.methods.PostMethod;
    /**
     * 用來演示提交XML格式數(shù)據(jù)的例子
     
    */

    public class PostXMLClient {
        
    public static void main(String[] args) throws Exception {
            File input 
    = new File(“test.xml”);
            PostMethod post 
    = new PostMethod(“http://localhost:8080/httpclient/xml.jsp”);
            
    // 設置請求的內(nèi)容直接從文件中讀取
         post.setRequestBody(new FileInputStream(input));
            
    if (input.length() < Integer.MAX_VALUE) 
               post.setRequestContentLength(input.length());
            
    else           
               post.setRequestContentLength(EntityEnclosingMethod.CONTENT_LENGTH_CHUNKED);
            
    // 指定請求內(nèi)容的類型
         post.setRequestHeader("Content-type""text/xml; charset=GBK");
            HttpClient httpclient 
    = new HttpClient(); 
            
    int result = httpclient.executeMethod(post); 
            System.out.println(
    "Response status code: " + result);
            System.out.println(
    "Response body: ");
            System.out.println(post.getResponseBodyAsString());
            post.releaseConnection();
        }

    }
     
    6.  通過HTTP上傳文件

    httpclient使用了單獨的一個HttpMethod子類來處理文件的上傳,這個類就是MultipartPostMethod,該類已經(jīng)封裝了文件上傳的細節(jié),我們要做的僅僅是告訴它我們要上傳文件的全路徑即可,下面的代碼片段演示如何使用這個類。

    MultipartPostMethod filePost = new MultipartPostMethod(targetURL);
    filePost.addParameter(
    "fileName", targetFilePath);
    HttpClient client 
    = new HttpClient();
    //由于要上傳的文件可能比較大,因此在此設置最大的連接超時時間
    client.getHttpConnectionManager().getParams().setConnectionTimeout(5000);
    int status = client.executeMethod(filePost); 
    上面代碼中,targetFilePath即為要上傳的文件所在的路徑。

    7.  訪問啟用認證的頁面

    我 們經(jīng)常會碰到這樣的頁面,當訪問它的時候會彈出一個瀏覽器的對話框要求輸入用戶名和密碼后方可,這種用戶認證的方式不同于我們在前面介紹的基于表單的用戶 身份驗證。這是HTTP的認證策略,httpclient支持三種認證方式包括:基本、摘要以及NTLM認證。其中基本認證最簡單、通用但也最不安全;摘 要認證是在HTTP  1.1中加入的認證方式,而NTLM則是微軟公司定義的而不是通用的規(guī)范,最新版本的NTLM是比摘要認證還要安全的一種方式。

    下面例子是從httpclient的CVS服務器中下載的,它簡單演示如何訪問一個認證保護的頁面:
    import org.apache.commons.httpclient.HttpClient;
    import org.apache.commons.httpclient.UsernamePasswordCredentials;
    import org.apache.commons.httpclient.methods.GetMethod;
    public class BasicAuthenticationExample {
       
    public BasicAuthenticationExample() {
        }

       
    public static void main(String[] args) throws Exception {
           HttpClient client 
    = new HttpClient();
            client.getState().setCredentials(
                
    "www.verisign.com",
                
    "realm",
                
    new UsernamePasswordCredentials("username""password")
            );
            GetMethod get 
    = new GetMethod("https://www.verisign.com/products/index.html";);
            get.setDoAuthentication( 
    true );
            
    int status = client.executeMethod( get );
            System.out.println(status
    +""+ get.getResponseBodyAsString());
            get.releaseConnection();
        }

    }
     
    8.  多線程模式下使用httpclient

    多 線程同時訪問httpclient,例如同時從一個站點上下載多個文件。對于同一個HttpConnection同一個時間只能有一個線程訪問,為了保證 多線程工作環(huán)境下不產(chǎn)生沖突,httpclient使用了一個多線程連接管理器的類: MultiThreadedHttpConnectionManager,要使用這個類很簡單,只需要在構造HttpClient實例的時候傳入即可,代 碼如下:
    MultiThreadedHttpConnectionManager connectionManager = 
       
    new MultiThreadedHttpConnectionManager();
    HttpClient client 
    = new HttpClient(connectionManager);
    posted on 2008-04-14 10:35 一凡 閱讀(10047) 評論(1)  編輯  收藏 所屬分類: OpenSource

    評論:
    # re: JAVA-用HttpClient來模擬瀏覽器GET,POST 2014-05-05 18:20 | zuidaima
    可以參考代碼:java apache commons HttpClient發(fā)送get和post請求的學習整理,下載地址:http://www.zuidaima.com/share/1754065983409152.htm  回復  更多評論
      
    主站蜘蛛池模板: 国产男女爽爽爽爽爽免费视频| 少妇性饥渴无码A区免费 | 亚洲精品乱码久久久久久按摩| 午夜亚洲乱码伦小说区69堂| 国产成人免费网站在线观看| 美女羞羞免费视频网站| 亚洲国产日产无码精品| 18禁美女黄网站色大片免费观看| 亚洲国产精品无码久久久蜜芽 | 久久精品国产免费观看三人同眠| 亚洲高清在线mv| 一区二区三区免费在线视频 | 久久不见久久见中文字幕免费| 久久亚洲色一区二区三区| 亚洲一级毛片中文字幕| 久久久久国色AV免费看图片| 亚洲综合激情五月丁香六月| 国产中文字幕免费| 九九热久久免费视频| 国产AV无码专区亚洲AV毛网站| 免费人成视频在线观看网站| 456亚洲人成影院在线观| 国产成人精品高清免费| 一级一级一片免费高清| 亚洲AV永久青草无码精品| 2020因为爱你带字幕免费观看全集 | 国产成人高清亚洲一区久久| 久久亚洲国产精品123区| 最近2019中文字幕免费直播| 亚洲欧美国产国产一区二区三区| 亚洲AV无码不卡在线观看下载| 你是我的城池营垒免费看| 亚洲理论在线观看| 国产又大又长又粗又硬的免费视频 | 亚洲精品无码乱码成人| 4399好看日本在线电影免费| 亚洲A∨精品一区二区三区下载 | 久久久久久久免费视频| 美女黄色毛片免费看| 亚洲AV无码专区在线播放中文| 免费A级毛片无码免费视|