ZT文萃

          本博不原創,轉帖自己感興趣那些事人物,什么入眼貼什么,隨心所欲。
          posts - 93, comments - 5, trackbacks - 0, articles - 0
            BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理

          httpclient的一些學習心得

          Posted on 2014-02-26 18:08 ZT文萃 閱讀(357) 評論(0)  編輯  收藏 所屬分類: 中間件
          轉載自:
          http://wallimn.iteye.com/blog/540566

          最近忙于一個項目,了解下httpclient,在這里總結出來,和大家一起學習分享,希望各位朋友提出寶貴的意見。

          首先介紹一下項目的背景:
            目標:把國內一家保險公司的“WEB一賬通”改成“WAP一賬通”。
            資源:客戶不提供任何的webservice接口。
           
          本項目中用到的第三方組件是apache的httpclient,一個非常強大的網頁抓取工具(抓這個字用得可能不太好), 這里和大家
          一起討論下httpclient的一些常用用法和要注意的地方。

          本文引用的資源列表:

            httpclient入門:  http://www.ibm.com/developerworks/cn/opensource/os-httpclient/
            httpclient證書導入:http://www.aygfsteel.com/happytian/archive/2006/12/22/89447.html
            httpclient高級認識:http://laohuang.iteye.com/blog/55613
            httpclient官方文檔:http://hc.apache.org/httpcomponents-client/index.html
            httpclient資源關閉:http://www.iteye.com/topic/234759
           
           
          上面的文章寫得很好,看完之后也就知道怎么用httpclient這個很好的工具了,但是在這里還是補充一些比較重要的東西,也是項目中經
          常碰到的問題。

          首先要注意的有以下幾點:
          1、httpclient連接后資源釋放問題很重要,就跟我們用database connection要釋放資源一樣。
          2、https網站采用ssl加密傳輸,證書導入要注意。
          3、做這樣的項目最好先了解下http協義,比如302,301,200,404返回代碼的含義(這是最基本的),cookie,session的機制。
          4、httpclient的redirect狀態默認是自動的,這在很大程度上給開發者很大的方便(如一些授權獲得cookie),但是有時要手動管理下,比如
            有時會遇到CircularRedirectException異常,出現這樣的情況是因為返回的頭文件中location值指向之前重復(端口號可以不同)地址,導致可能會出現死
            循環遞歸重定向,這時可以手動關閉:method.setFollowRedirects(false)
          5、有的網站會先判別用戶的請求是否是來自瀏覽器,如不是,則返回不正確的文本,所以用httpclient抓取信息時在頭部加入如下信息:
            header.put("User-Agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; QQDownload 1.7; .NET CLR 1.1.4322; CIBA; .NET CLR 2.0.50727)");
          6、當post請求提交數據時要改變默認編碼,不然的話提交上去的數據會出現亂碼。重寫postMethod的setContentCharSet()方法就可以了:





           
          下面寫一個通用類來處理request請求返回的文本:
          Java代碼  收藏代碼
          1. /* 
          2.  * HttpRequestProxy.java 
          3.  * 
          4.  * Created on November 3, 2008, 9:53 AM 
          5.  */  
          6.   
          7. package cn.com.mozat.net;  
          8.   
          9. import java.io.BufferedReader;  
          10. import java.io.IOException;  
          11. import java.io.InputStream;  
          12. import java.io.InputStreamReader;  
          13. import java.util.HashMap;  
          14. import java.util.Iterator;  
          15. import java.util.Map;  
          16. import java.util.Set;  
          17.   
          18. import org.apache.commons.httpclient.Header;  
          19. import org.apache.commons.httpclient.HttpClient;  
          20. import org.apache.commons.httpclient.HttpException;  
          21. import org.apache.commons.httpclient.HttpMethod;  
          22. import org.apache.commons.httpclient.NameValuePair;  
          23. import org.apache.commons.httpclient.SimpleHttpConnectionManager;  
          24. import org.apache.commons.httpclient.methods.GetMethod;  
          25. import org.apache.commons.httpclient.methods.PostMethod;  
          26.   
          27. import cn.com.mozat.exception.CustomException;  
          28.   
          29. /** 
          30.  *  
          31.  * @author bird  email:lihongfu-84@163.com 
          32.  * 
          33.  * 2008-11-4  09:49:48 
          34.  */  
          35. public class HttpRequestProxy{  
          36.     //超時間隔  
          37.     private static int connectTimeOut = 60000;  
          38.  //讓connectionmanager管理httpclientconnection時是否關閉連接  
          39.     private static boolean alwaysClose = false;  
          40.  //返回數據編碼格式  
          41.     private String encoding = "UTF-8";  
          42.       
          43.     private final HttpClient client = new HttpClient(new SimpleHttpConnectionManager(alwaysClose));  
          44.    
          45.     public HttpClient getHttpClient(){  
          46.         return client;  
          47.     }  
          48.         
          49.     /** 
          50.      * 用法: 
          51.      * HttpRequestProxy hrp = new HttpRequestProxy(); 
          52.      * hrp.doRequest("http://www.163.com",null,null,"gbk"); 
          53.      *  
          54.      * @param url  請求的資源URL 
          55.      * @param postData  POST請求時form表單封裝的數據 沒有時傳null 
          56.      * @param header   request請求時附帶的頭信息(header) 沒有時傳null 
          57.      * @param encoding response返回的信息編碼格式 沒有時傳null 
          58.      * @return  response返回的文本數據 
          59.      * @throws CustomException  
          60.      */  
          61.     public String doRequest(String url,Map postData,Map header,String encoding) throws CustomException{  
          62.      String responseString = null;  
          63.      //頭部請求信息  
          64.      Header[] headers = null;  
          65.      if(header != null){  
          66.       Set entrySet = header.entrySet();  
          67.          int dataLength = entrySet.size();  
          68.           headers= new Header[dataLength];  
          69.          int i = 0;  
          70.          for(Iterator itor = entrySet.iterator();itor.hasNext();){  
          71.           Map.Entry entry = (Map.Entry)itor.next();  
          72.           headers[i++] = new Header(entry.getKey().toString(),entry.getValue().toString());  
          73.          }  
          74.      }  
          75.      //post方式  
          76.         if(postData!=null){  
          77.          PostMethod postRequest = new PostMethod(url.trim());  
          78.          if(headers != null){  
          79.           for(int i = 0;i < headers.length;i++){  
          80.            postRequest.setRequestHeader(headers[i]);  
          81.           }  
          82.          }  
          83.          Set entrySet = postData.entrySet();  
          84.          int dataLength = entrySet.size();  
          85.          NameValuePair[] params = new NameValuePair[dataLength];  
          86.          int i = 0;  
          87.          for(Iterator itor = entrySet.iterator();itor.hasNext();){  
          88.           Map.Entry entry = (Map.Entry)itor.next();  
          89.           params[i++] = new NameValuePair(entry.getKey().toString(),entry.getValue().toString());  
          90.          }  
          91.          postRequest.setRequestBody(params);  
          92.          try {  
          93.     responseString = this.executeMethod(postRequest,encoding);  
          94.    } catch (CustomException e) {  
          95.     throw e;  
          96.    } finally{  
          97.     postRequest.releaseConnection();  
          98.    }  
          99.         }  
          100.       //get方式  
          101.         if(postData == null){  
          102.          GetMethod getRequest = new GetMethod(url.trim());  
          103.          if(headers != null){  
          104.           for(int i = 0;i < headers.length;i++){  
          105.            getRequest.setRequestHeader(headers[i]);  
          106.           }  
          107.          }  
          108.          try {  
          109.     responseString = this.executeMethod(getRequest,encoding);  
          110.    } catch (CustomException e) {  
          111.                 e.printStackTrace();  
          112.     throw e;  
          113.    }finally{  
          114.     getRequest.releaseConnection();  
          115.    }  
          116.         }  
          117.    
          118.         return responseString;  
          119.     }  
          120.   
          121.  private String executeMethod(HttpMethod request, String encoding) throws CustomException{  
          122.   String responseContent = null;  
          123.   InputStream responseStream = null;  
          124.   BufferedReader rd = null;  
          125.   try {  
          126.    this.getHttpClient().executeMethod(request);  
          127.    if(encoding != null){  
          128.     responseStream = request.getResponseBodyAsStream();  
          129.      rd = new BufferedReader(new InputStreamReader(responseStream,  
          130.                       encoding));  
          131.               String tempLine = rd.readLine();  
          132.               StringBuffer tempStr = new StringBuffer();  
          133.               String crlf=System.getProperty("line.separator");  
          134.               while (tempLine != null)  
          135.               {  
          136.                   tempStr.append(tempLine);  
          137.                   tempStr.append(crlf);  
          138.                   tempLine = rd.readLine();  
          139.               }  
          140.               responseContent = tempStr.toString();  
          141.    }else  
          142.     responseContent = request.getResponseBodyAsString();  
          143.              
          144.    Header locationHeader = request.getResponseHeader("location");  
          145.    //返回代碼為302,301時,表示頁面己經重定向,則重新請求location的url,這在  
          146.    //一些登錄授權取cookie時很重要  
          147.    if (locationHeader != null) {  
          148.              String redirectUrl = locationHeader.getValue();  
          149.              this.doRequest(redirectUrl, null, null,null);  
          150.          }  
          151.   } catch (HttpException e) {  
          152.    throw new CustomException(e.getMessage());  
          153.   } catch (IOException e) {  
          154.    throw new CustomException(e.getMessage());  
          155.   
          156.   } finally{  
          157.    if(rd != null)  
          158.     try {  
          159.      rd.close();  
          160.     } catch (IOException e) {  
          161.      throw new CustomException(e.getMessage());  
          162.     }  
          163.     if(responseStream != null)  
          164.      try {  
          165.       responseStream.close();  
          166.      } catch (IOException e) {  
          167.       throw new CustomException(e.getMessage());  
          168.   
          169.      }  
          170.   }  
          171.   return responseContent;  
          172.  }  
          173.    
          174.      
          175.  /** 
          176.   * 特殊請求數據,這樣的請求往往會出現redirect本身而出現遞歸死循環重定向 
          177.   * 所以單獨寫成一個請求方法 
          178.   * 比如現在請求的url為:http://localhost:8080/demo/index.jsp 
          179.   * 返回代碼為302 頭部信息中location值為:http://localhost:8083/demo/index.jsp 
          180.   * 這時httpclient認為進入遞歸死循環重定向,拋出CircularRedirectException異常 
          181.   * @param url 
          182.   * @return 
          183.   * @throws CustomException  
          184.   */  
          185.  public String doSpecialRequest(String url,int count,String encoding) throws CustomException{  
          186.   String str = null;  
          187.   InputStream responseStream = null;  
          188.   BufferedReader rd = null;  
          189.   GetMethod getRequest = new GetMethod(url);  
          190.   //關閉httpclient自動重定向動能  
          191.   getRequest.setFollowRedirects(false);  
          192.   try {  
          193.      
          194.    this.client.executeMethod(getRequest);  
          195.    Header header = getRequest.getResponseHeader("location");  
          196.    if(header!= null){  
          197.     //請求重定向后的URL,count同時加1  
          198.     this.doSpecialRequest(header.getValue(),count+1, encoding);  
          199.    }  
          200.    //這里用count作為標志位,當count為0時才返回請求的URL文本,  
          201.    //這樣就可以忽略所有的遞歸重定向時返回文本流操作,提高性能  
          202.    if(count == 0){  
          203.     getRequest = new GetMethod(url);  
          204.     getRequest.setFollowRedirects(false);  
          205.     this.client.executeMethod(getRequest);  
          206.     responseStream = getRequest.getResponseBodyAsStream();  
          207.     rd = new BufferedReader(new InputStreamReader(responseStream,  
          208.                       encoding));  
          209.              String tempLine = rd.readLine();  
          210.              StringBuffer tempStr = new StringBuffer();  
          211.              String crlf=System.getProperty("line.separator");  
          212.              while (tempLine != null)  
          213.              {  
          214.                  tempStr.append(tempLine);  
          215.                  tempStr.append(crlf);  
          216.                  tempLine = rd.readLine();  
          217.              }  
          218.              str = tempStr.toString();  
          219.    }  
          220.      
          221.   } catch (HttpException e) {  
          222.    throw new CustomException(e.getMessage());  
          223.   } catch (IOException e) {  
          224.    throw new CustomException(e.getMessage());  
          225.   } finally{  
          226.    getRequest.releaseConnection();  
          227.    if(rd !=null)  
          228.     try {  
          229.      rd.close();  
          230.     } catch (IOException e) {  
          231.      throw new CustomException(e.getMessage());  
          232.     }  
          233.     if(responseStream !=null)  
          234.      try {  
          235.       responseStream.close();  
          236.      } catch (IOException e) {  
          237.       throw new CustomException(e.getMessage());  
          238.      }  
          239.   }  
          240.   return str;  
          241.  }  
          242.    
          243.    
          244.    
          245.    
          246.  public static void main(String[] args) throws Exception{  
          247.   HttpRequestProxy hrp = new HttpRequestProxy();  
          248.    Map header = new HashMap();  
          249.          header.put("User-Agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; QQDownload 1.7; .NET CLR 1.1.4322; CIBA; .NET CLR 2.0.50727)");  
          250.   String str = hrp.doRequest(  
          251.     "http://www.cma-cgm.com/en/eBusiness/Tracking/Default.aspx?BolNumber=GZ2108827",  
          252.      null, header,null);  
          253.   System.out.println(str.contains("row_CRXU1587647"));  
          254. //  System.out.println(str);  
          255.  }  
          256.      

          主站蜘蛛池模板: 莒南县| 延安市| 华池县| 阿拉善右旗| 建阳市| 杂多县| 安福县| 徐闻县| 禄丰县| 通江县| 亚东县| 万源市| 武胜县| 崇阳县| 沈丘县| 丽水市| 吉安县| 太仓市| 景东| 普定县| 中山市| 上犹县| 太原市| 电白县| 浠水县| 平山县| 温宿县| 长岭县| 柳州市| 湟源县| 富锦市| 万载县| 名山县| 新晃| 延庆县| 象山县| 黄石市| 兰考县| 北流市| 余江县| 洪泽县|