posts - 325,  comments - 25,  trackbacks - 0
          最近忙于一個項目,了解下httpclient,在這里總結(jié)出來,和大家一起學習分享,希望各位朋友提出寶貴的意見。 

          首先介紹一下項目的背景: 
            目標:把國內(nèi)一家保險公司的“WEB一賬通”改成“WAP一賬通”。 
            資源:客戶不提供任何的webservice接口。 
            
          本項目中用到的第三方組件是apache的httpclient,一個非常強大的網(wǎng)頁抓取工具(抓這個字用得可能不太好), 這里和大家 
          一起討論下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這個很好的工具了,但是在這里還是補充一些比較重要的東西,也是項目中經(jīng) 
          常碰到的問題。 

          首先要注意的有以下幾點: 
          1、httpclient連接后資源釋放問題很重要,就跟我們用database connection要釋放資源一樣。 
          2、https網(wǎng)站采用ssl加密傳輸,證書導入要注意。 
          3、做這樣的項目最好先了解下http協(xié)義,比如302,301,200,404返回代碼的含義(這是最基本的),cookie,session的機制。 
          4、httpclient的redirect狀態(tài)默認是自動的,這在很大程度上給開發(fā)者很大的方便(如一些授權獲得cookie),但是有時要手動管理下,比如 
            有時會遇到CircularRedirectException異常,出現(xiàn)這樣的情況是因為返回的頭文件中l(wèi)ocation值指向之前重復(端口號可以不同)地址,導致可能會出現(xiàn)死 
            循環(huán)遞歸重定向,這時可以手動關閉:method.setFollowRedirects(false) 
          5、有的網(wǎng)站會先判別用戶的請求是否是來自瀏覽器,如不是,則返回不正確的文本,所以用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請求提交數(shù)據(jù)時要改變默認編碼,不然的話提交上去的數(shù)據(jù)會出現(xiàn)亂碼。重寫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.  //返回數(shù)據(jù)編碼格式  
          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表單封裝的數(shù)據(jù) 沒有時傳null 
          56.      * @param header   request請求時附帶的頭信息(header) 沒有時傳null 
          57.      * @param encoding response返回的信息編碼格式 沒有時傳null 
          58.      * @return  response返回的文本數(shù)據(jù) 
          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時,表示頁面己經(jīng)重定向,則重新請求location的url,這在  
          146.    //一些登錄授權取cookie時很重要  
          147.    if (locationHeader != null) {  
          148.              String redirectUrl = locationHeader.getValue();  
          149.              this.doRequest(redirectUrl, nullnull,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.   * 特殊請求數(shù)據(jù),這樣的請求往往會出現(xiàn)redirect本身而出現(xiàn)遞歸死循環(huán)重定向 
          177.   * 所以單獨寫成一個請求方法 
          178.   * 比如現(xiàn)在請求的url為:http://localhost:8080/demo/index.jsp 
          179.   * 返回代碼為302 頭部信息中l(wèi)ocation值為:http://localhost:8083/demo/index.jsp 
          180.   * 這時httpclient認為進入遞歸死循環(huán)重定向,拋出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.      
          257. }  
          posted on 2015-08-20 13:04 長春語林科技 閱讀(226) 評論(0)  編輯  收藏 所屬分類: android
          <2015年8月>
          2627282930311
          2345678
          9101112131415
          16171819202122
          23242526272829
          303112345

           

          長春語林科技歡迎您!

          常用鏈接

          留言簿(6)

          隨筆分類

          隨筆檔案

          文章分類

          文章檔案

          相冊

          收藏夾

          搜索

          •  

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 遵义县| 东莞市| 高雄市| 建平县| 哈巴河县| 新乐市| 玛曲县| 大化| 金门县| 桃江县| 武邑县| 桐乡市| 淮南市| 建湖县| 嵊泗县| 海阳市| 拉萨市| 彝良县| 台东县| 邛崃市| 沁阳市| 包头市| 榕江县| 上饶县| 井陉县| 新安县| 海林市| 恩施市| 三江| 长汀县| 乐至县| 晋城| 柳州市| 贵德县| 南和县| 喀喇| 灵石县| 侯马市| 鄂托克前旗| 阿拉善盟| 崇仁县|