HttpClient初步使用方法

工程師WWW發表於2015-06-15

             HttpClient簡單使用

準備

         Apache官網下載 HttpClient , 下不了的點選這裡,下載完後解壓取lib資料夾中jar包匯入到專案中, 還需要匯入commons-logging-1.2.jar包

在進行本例之前需要了解三個類

         HttpClient  代表Http客戶端 裡面定義了很多http 請求執行行為

         HttpEntity  訊息載體,傳送或者接收訊息的載體,可以通過客戶端請求或者伺服器響應獲取例項

         HttpConnection  代表http連線

本次例項程式碼

  1. public class HttpCLientDemo  
  2. {  
  3.   
  4.     // HttpClient 代表Http客戶端   
  5.     // HttpEntity 訊息載體,傳送或者接收訊息的載體,可以通過客戶端請求或者伺服器響應獲取例項  
  6.     // HttpConnection 代表http連線  
  7.     /** 
  8.      * @param args 
  9.      */  
  10.     public static void main(String[] args)  
  11.     {  
  12.         // 建立預設的客戶端例項  
  13.         HttpClient httpCLient = new DefaultHttpClient();  
  14.           
  15.         // 建立get請求例項  
  16.         HttpGet httpget = new HttpGet("http://www.baidu.com");  
  17.           
  18.         System.out.println("executing request "+httpget.getURI());  
  19.           
  20.         try  
  21.         {  
  22.               
  23.             // 客戶端執行get請求 返回響應實體  
  24.             HttpResponse response = httpCLient.execute(httpget);  
  25.               
  26.             // 伺服器響應狀態行  
  27.             System.out.println(response.getStatusLine());  
  28.               
  29.             Header[] heads = response.getAllHeaders();  
  30.             // 列印所有響應頭  
  31.             for(Header h:heads){  
  32.                 System.out.println(h.getName()+":"+h.getValue());  
  33.             }  
  34.               
  35.             // 獲取響應訊息實體  
  36.             HttpEntity entity = response.getEntity();  
  37.               
  38.             System.out.println("------------------------------------");  
  39.               
  40.               
  41.               
  42.             if(entity != null){  
  43.                                   
  44.                 //響應內容  
  45.                 System.out.println(EntityUtils.toString(entity));  
  46.                   
  47.                 System.out.println("----------------------------------------");  
  48.                 // 響應內容長度  
  49.                 System.out.println("響應內容長度:"+entity.getContentLength());  
  50.             }  
  51.               
  52.         } catch (ClientProtocolException e){  
  53.             e.printStackTrace();  
  54.         } catch (IOException e){  
  55.             e.printStackTrace();  
  56.         }finally{  
  57.             httpCLient.getConnectionManager().shutdown();  
  58.         }  
  59.     }  
  60.   
  61. }  

本次執行結果


總結一下

      使用之前匯入相應的jar包,然後開始編碼,先建立一個客戶端,根據需求可以配置,接著例項一個請求(get post put。。。),

      然後用客戶端對某一個伺服器執行請求操作,可以得到一個http響應,

      這裡響應 結構如下 訊息狀態行,訊息頭,訊息實體

       Response  =   Status-Line
                     *(( general-header
                      | response-header
                      | entity-header ) CRLF)
                     CRLF
                     [ message-body ]


結構中的資料我已在本例執行結果中顯示出來,請見上圖,可以看出本例:

對應結構

訊息狀態行:

               HTTP/1.1 200 OK

訊息響應頭:

Date:Tue, 08 Jan 2013 07:18:42 GMT
Server:BWS/1.0
Content-Length:9785
Content-Type:text/html;charset=gbk
Cache-Control:private
Expires:Tue, 08 Jan 2013 07:18:42 GMT
Set-Cookie:H_PS_PSSID=1757; path=/; domain=.baidu.com
Set-Cookie:BAIDUID=22B4BB1F8F8E808DB50B6513DBBCF6DF:FG=1; expires=Tue, 08-Jan-43 07:18:42 GMT; path=/; domain=.baidu.com
P3P:CP=" OTI DSP COR IVA OUR IND COM "
Connection:Keep-Alive

  訊息實體:百度網頁原始碼我就不寫了


本次對HttpClient的簡單使用到此為止

-----------------------------------------------------------

簡介

     最近在做一些開放介面應用的時候發現原有的一些應用大量使用了HttpComponent裡面的功能。從HttpComponent本身的介紹來說,它是一個實現Http協議很多操作功能的元件,在一些爬蟲和網路應用開發中都得到大量的應用。因為牽涉到的開放服務介面使用的是http rest服務,感覺httpcomponent很適合其中的場景。這裡結合專案中使用的一些場景來對其中的功能做一個簡單的總結。

HttpClient基本操作

     在使用httpclient之前我們需要首先下載httpclient的jar包,裡面就包含了httpclient.jar, httpcore.jar等幾個檔案。我們先看一個簡單的示例:

Java程式碼  收藏程式碼
  1. import java.io.BufferedReader;  
  2. import java.io.IOException;  
  3. import java.io.InputStreamReader;  
  4.   
  5. import org.apache.http.HttpResponse;  
  6. import org.apache.http.client.ClientProtocolException;  
  7. import org.apache.http.client.HttpClient;  
  8. import org.apache.http.client.methods.HttpGet;  
  9. import org.apache.http.impl.client.DefaultHttpClient;  
  10.   
  11.   
  12. public class HTTPGetSample {  
  13.     public static void main(String[] args) throws ClientProtocolException, IOException {  
  14.         String url = "http://www.google.com.hk/search?q=httpClient";  
  15.           
  16.         HttpClient client = new DefaultHttpClient();  
  17.         HttpGet request = new HttpGet(url);  
  18.           
  19.         HttpResponse response = client.execute(request);  
  20.         System.out.println("Response Code: " +  
  21.         response.getStatusLine().getStatusCode());  
  22.           
  23.         BufferedReader rd = new BufferedReader(  
  24.             new InputStreamReader(response.getEntity().getContent()));  
  25.         String line = "";  
  26.         while((line = rd.readLine()) != null) {  
  27.         System.out.println(line);  
  28.         }  
  29.     }  
  30. }  

     在這個示例裡我們嘗試用httpclient傳送一個http get請求。請求的地址是對應到一個google search的url.仔細看上面的程式碼,其實還是很簡單,首先建立一個HttpClient的物件,然後針對我們的http get操作建立一個HttpGet物件,並將請求url作為引數傳給該物件。具體執行get操作的步驟是通過httpclient.execute()方法。這個方法裡將HttpGet物件作為引數傳入。返回一個HttpResponse的結果。

    我們通過讀取HttpResponse的結果就可以得到請求返回的詳細資訊。這個過程和我們通過瀏覽器瀏覽某個網頁的效果相同。程式執行的部分結果如下:

Java程式碼  收藏程式碼
  1. Response Code: 200  
  2. <!doctype html><html itemscope="itemscope" itemtype="http://schema.org/WebPage"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">...  

    由於篇幅限制,省略了部分結果。

    從前面示例裡我們可以看到通過HttpClient傳送Http請求的基本套路:

1. 建立HttpClient物件。

2. 構造Http 請求物件。

3. 執行HttpClient物件的execute方法,將Http請求物件作為該方法的引數。

4. 讀取execute方法返回的HttpResponse結果並解析。

    ok,既然整體過程是這樣的話,我們後續使用post, put, delete等操作的過程也就大同小異了。在詳細討論這些方法使用之前我們先簡單的討論一下http協議裡的這幾種方法。

Http協議常用方法

     關於http協議的介紹網上材料很多。總的來說,http協議規範了通訊雙方互動的方式,基本上它是採用一種請求-應答的方式。客戶端傳送請求給伺服器端,然後伺服器端傳送響應回來。我們常用的幾種http操作的方法可以分為可修改的和不可修改的。怎麼理解這個可修改和不可修改的意思呢?

    在http協議裡,我們有的請求方法只是獲取伺服器端資源的資訊,預設的假定是不修改伺服器端的狀態,這種方法稱為不可修改的方法。比如說HttpGet, HttpHead, HttpOptions,HttpTrace。所以說這種請求方法是可以重複執行並返回相同結果的。我們對同一個資源執行若干次get操作,每次得到的結果都相同。而對於可修改的請求來說,主要有HttpPut, HttpPost, HttpDelete等。他們在規範裡分別對應著對資源的update, create和delete等操作。所以在一些web應用裡,我們提交表單的時候選擇的是http post操作。

     除了http協議裡規定的這麼幾種方法,它本身還支援互動的內容,比如通過請求頭中間設定"accept", "Content-Type"等資訊,指定我們互動的內容格式。他們可以是靜態檔案型別的,比如說txt, .gif,.jpg等,也可以是一些其他文字如json, xml。在一些rest web服務裡面,我們指定的支援json或者xml格式的資料交換就可以通過這裡來定義。

     我們剛看到了通過設定請求頭來指定通訊的互動內容格式,那麼是否也可以指定請求體呢?在這裡是有可能的,只是針對不同的請求方法。比如說對HttpGet之類的方法,他們本身只是獲取伺服器的內容不需要向伺服器提交額外的資訊,所以對於這一類的請求方法來說帶個請求體意義並不大。而對於那些要提交大量內容給伺服器的請求如上傳檔案或者提交表單資訊的httpput, httppost請求,他們就有必要設定一個請求體。

    有了前面的這些鋪墊,我們後面可以更加深入的分析一下httpclient中間幾種方法的結構和用法。

 Http操作方法結構

    HttpClient相關的uml結構圖如下:

 

    我們關注的各種http方法都被定義成一個個獨立的類,他們都繼承自HttpRequestBase。其中比較特殊一點的是HttpPut, HttpPost,他們繼承自HttpEntityEnclosingRequestBase。為什麼這兩個類要稍微特殊一點呢?這就是我們前面提到的他們要設定請求體,在HttpEntityEnclosingRequestBase裡有HttpEntity的成員變數,他們作為這兩個方法特定的特性定義在這裡:

Java程式碼  收藏程式碼
  1. private HttpEntity entity;  
  2.   
  3. public HttpEntity getEntity() {  
  4.     return this.entity;  
  5. }  
  6.   
  7. public void setEntity(final HttpEntity entity) {  
  8.     this.entity = entity;  
  9. }  

     HttpEntity是一個介面,根據具體傳入的引數型別我們可以選擇StringEntity, InputStreamEntity等。由此,對於這兩種有差別的請求方法來說,他們只是需要多增加一個setEntity的方法。

    另外對於通用的設定請求頭部分,前面的示例程式碼裡我們是使用了一種硬編碼的方式。我們也可以採用request.addHeader(Header)的方法。在HttpClient裡,Header是一個介面,我們可以建立兩種實現該介面的物件來作為引數傳給addHeader方法。分別是BasicHeader, BufferedHeader。

 

總結

     HttpClient通常用來作為一個模擬http請求的工具。我們最常見的get, put, post, delete等方法在其中都通過具體定義的類來實現。當我們要傳送某個具體的請求是,只需要建立對應請求的物件並設定請求頭或者請求體,執行HttpClient的execute方法就可以得到執行結果了。返回的HttpResponse訊息體結果具體內容是一個InputStream,我們可以根據需要來讀取內容。返回的訊息頭則是顯示http操作方法的執行結果,我們可以根據訊息頭來判斷請求執行是否正確,結果是否執行完畢以及如果出錯了錯誤的緣由可能是什麼等資訊。關於HttpClient的更多實現和應用後面會進一步學習研究。

參考材料

HttpComponent website




在我們對http的資源進行請求的時候,我們可以通過get和post 這個2種方式

      用get獲取資訊,所需要提交的內容是體現在url中的,通常的形式是以:http://www.xxxxx.com?id=xxxxx&pass=xxxxxx  “?”前面是的網址,”?”後面的是提交的內容

 例如:我們在百度中 打入nba,則請求的url 就為:http://www.baidu.com/s?wd=nba&rsv_bp=0&rsv_spt=3&rsv_sug3=3&rsv_sug=0&rsv_sug4=157&rsv_sug1=1&inputT=940 ,它所提交的內容在url中時可見的。而用post方式提交呢,它提交的內容我們是不可見的。如果我們要寫一個自動post 表單資料的程式,那我們就得先知道傳送這個post請求需要那些資料選項。

例如 :http://www.sxgjj.gov.cn/querygjj.aspx 是一個查詢的頁面,我們通過瀏覽器的開發者工具(按F12)來檢視該頁面html


可以看到這裡提交表單的方式是用post

現在我們通過瀏覽器輸入查詢的身份證號碼和姓名,提交之後,我們就可以在開發者工具裡檢視psot 表單的資料內容了!



從上圖可以得出我們需要提交的post 內容有 _viewstate,_eventvalidation,tbx_pername,tbx_pidcard,tbx_bankAccout,btn_Querry這幾項內容

   知道了這些,我們就可以通過程式來自動完成post請求了

   我是通過httpclient這個元件來完成的,HttpClient 是 Apache Jakarta Common 下的子專案,可以用來提供高效的、最新的、功能豐富的支援 HTTP 協議的客戶端程式設計工具包,網上有很多關於它的介紹,有興趣的可以自己去了解。以下就是實現的程式碼(記得把httpclient的lib檔案裡的jar檔案匯入到你的工程專案中區)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
import java.io.*;
import java.sql.*;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.InputStreamEntity;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.apache.http.*;
 
public class httpclient {
 
public static void post_comment(String pdcode,String psname,String id,HttpClient httpclient) throws Exception{
 
                try {
                    //構造一個post物件
                 HttpPost httpPost = new HttpPost("http://www.sxgjj.gov.cn/querygjj.aspx");
                 //新增所需要的post內容
                 List<NameValuePair> nvps = new ArrayList<NameValuePair>();
                 nvps.add(new BasicNameValuePair("__VIEWSTATE", "/wEPDwUKMTI3ODgyMTE1M2RkYvz2pJOChArFWd3j+6npOZr96OI="));
                 nvps.add(new BasicNameValuePair("__EVENTVALIDATION", "/wEWBQLzxcLpBgL3n9/ACwLuubGjBgKs9/TJDwLvjry/BYt++cnimkGWb2qATgw5QzGksEj8"));
                 nvps.add(new BasicNameValuePair("tbx_pername", psname));
                 nvps.add(new BasicNameValuePair("tbx_PidCard", pdcode));
                 nvps.add(new BasicNameValuePair("tbx_bankAccount", ""));
                 nvps.add(new BasicNameValuePair("btnQuery", "查詢"));
                  
 
                 httpPost.setEntity(new UrlEncodedFormEntity(nvps, Consts.UTF_8));
 
                 HttpResponse response = httpclient.execute(httpPost);
 
                 HttpEntity entity = response.getEntity();
                // EntityUtils.consume(entity);
                String Filename = "e:\\gjj\\"+ id+".txt";
                 
                createNewFile(Filename,EntityUtils.toString(entity))
 
                }       
                finally {
                    System.out.println("ok!");
                }    
         
         }
    
  public static void main(String[] args) throws Exception {
 
HttpClient httpclient =new DefaultHttpClient();
post_comment(“330621xxxxxxxxxxxx”,"張三","test",httpclient);
httpclient.getConnectionManager().shutdown();
 
}
}


相關文章