程式扎記: [ Java 代碼範本 ] Java 模擬 Http Get 與 Post query

標籤

2010年9月10日 星期五

[ Java 代碼範本 ] Java 模擬 Http Get 與 Post query


轉載自 這裡
前言 :
要達到基本的Http get與post方法取得網站內容,Java內的URLConnection就可以達成。
但我實作時發現它太過於底層,以致於我不知該如何做到關於Session狀態的延續,也就是不能夠在完成登入後,保留住登入狀態然後進入下個動作。
於是就尋求別的作法,最後發現了Apache有提供了HttpClient套件的JAR檔,能讓我們用更簡單的方式達成工作。
在此參考網路上的文章:用HttpClient來模擬瀏覽器GET,POST,加上可自動轉導的功能,包成函式。
另外再加上可用三種類型來設定傳遞的參數,並控制其連線與中斷狀態.

下載套件 :
到 HttpClient Download 下載套件,選擇Binary with dependencies的版本(如4.0.1.zip),
我們需要的JAR在該壓縮檔中的lib目錄下。會用到的JAR檔有三個:
- commons-logging-1.1.1.jar
- httpclient-4.0.1.jar
- httpcore-4.0.1.jar

範例代碼 :
- HTTPBaseIO.java 代碼 :
  1. package john.net;  
  2.   
  3. import java.io.BufferedReader;  
  4. import java.io.IOException;  
  5. import java.io.InputStream;  
  6. import java.io.InputStreamReader;  
  7. import java.io.UnsupportedEncodingException;  
  8. import java.net.URLEncoder;  
  9. import java.util.ArrayList;  
  10. import java.util.HashMap;  
  11. import java.util.List;  
  12.   
  13. import org.apache.http.Header;  
  14. import org.apache.http.HttpEntity;  
  15. import org.apache.http.HttpHost;  
  16. import org.apache.http.HttpResponse;  
  17. import org.apache.http.HttpStatus;  
  18. import org.apache.http.NameValuePair;  
  19. import org.apache.http.client.ClientProtocolException;  
  20. import org.apache.http.client.entity.UrlEncodedFormEntity;  
  21. import org.apache.http.client.methods.HttpGet;  
  22. import org.apache.http.client.methods.HttpPost;  
  23. import org.apache.http.client.methods.HttpUriRequest;  
  24. import org.apache.http.conn.params.ConnRoutePNames;  
  25. import org.apache.http.entity.StringEntity;  
  26. import org.apache.http.impl.client.DefaultHttpClient;  
  27. import org.apache.http.message.BasicNameValuePair;  
  28. import org.apache.http.protocol.HTTP;  
  29.   
  30. public class HTTPBaseIO {  
  31. public enum Method {  
  32.   get, post  
  33. }  
  34.   
  35. private DefaultHttpClient httpclient = null;  
  36. private boolean isClosedConn = false;  
  37. private String newuri = null;  
  38. private int statuscode = HttpStatus.SC_NO_CONTENT;  
  39.   
  40. private HttpHost proxy = null;  
  41.   
  42. public HTTPBaseIO(){  
  43.     
  44. }  
  45. public HTTPBaseIO(String proxyIP,int proxyPort){  
  46.   setProxy(proxyIP,proxyPort);  
  47. }  
  48. public HTTPBaseIO(HttpHost proxy){  
  49.   setProxy(proxy);  
  50. }  
  51.   
  52. /** 
  53.   * 取得使用的proxy 
  54.   */  
  55. public HttpHost getProxy() {  
  56.   return proxy;  
  57. }  
  58.   
  59. /** 
  60.   * 設定proxy 
  61.   */  
  62. public void setProxy(HttpHost proxy) {  
  63.   this.proxy = proxy;  
  64. }  
  65.   
  66. /** 
  67.   * 設定proxy 
  68.   *  
  69.   * @param ip 
  70.   *            proxy的IP(hostname) 
  71.   * @param port 
  72.   *            proxy的Port 
  73.   */  
  74. public void setProxy(String ip, int port) {  
  75.   if(ip!=null)  
  76.    proxy = new HttpHost(ip, port);  
  77. }  
  78.   
  79. /** 
  80.   * 取得回應後所得到的代碼,可參考org.apache.http.HttpStatus類別 
  81.   *  
  82.   * @return org.apache.http.HttpStatus 
  83.   */  
  84. public int getStatuscode() {  
  85.   return statuscode;  
  86. }  
  87.   
  88. /** 
  89.   * 如果是轉導的狀態所得到的URI 
  90.   *  
  91.   * @return 
  92.   */  
  93. public String getNewuri() {  
  94.   return newuri;  
  95. }  
  96.   
  97. public void resetNewuri() {  
  98.   newuri = null;  
  99. }  
  100.   
  101. /** 
  102.   * 取得連線物件 
  103.   *  
  104.   * @return 
  105.   */  
  106. public DefaultHttpClient getHttpclient() {  
  107.   return httpclient;  
  108. }  
  109.   
  110. /** 
  111.   * 設定連線物件 
  112.   *  
  113.   * @param httpclient 
  114.   */  
  115. public void setHttpclient(DefaultHttpClient httpclient) {  
  116.   this.httpclient = httpclient;  
  117. }  
  118.   
  119. /** 
  120.   * 是否已關閉連線 
  121.   *  
  122.   * @return 
  123.   */  
  124. public boolean isClosedConn() {  
  125.   return isClosedConn;  
  126. }  
  127.   
  128. /** 
  129.   * 關閉連線 
  130.   */  
  131. public void closeConn() {  
  132.   closeConn(true);  
  133. }  
  134.   
  135. /** 
  136.   * 關閉連線 
  137.   *  
  138.   * @param isCloseConn 
  139.   *            是否關閉 
  140.   */  
  141. public void closeConn(boolean isCloseConn) {  
  142.   if (isCloseConn && httpclient != null && !isClosedConn) {  
  143.    httpclient.getConnectionManager().shutdown();  
  144.    httpclient = null;  
  145.    isClosedConn = true;  
  146.   }  
  147. }  
  148.   
  149. /** 
  150.   * 取得網頁內容 
  151.   *  
  152.   * @param urlpath 
  153.   *            網址 
  154.   * @param method 
  155.   *            Method.get or Method.post 
  156.   * @param params 
  157.   *            參數 
  158.   * @param charset 
  159.   *            編碼,如HTTP.UTF_8 
  160.   * @param isAutoRedirect 
  161.   *            如果網頁回應狀態為轉導到新網頁,且Header的location有值,則自己以location所指網址取得內容 
  162.   * @param isCloseConn 
  163.   *            是否關閉連線 
  164.   * @return 失敗回傳null,成功回傳網頁HTML 
  165.   * @throws ClientProtocolException 
  166.   * @throws IOException 
  167.   */  
  168. public String doSend(String urlpath, Method method, String params,  
  169.    String charset, boolean isAutoRedirect, boolean isCloseConn)  
  170.    throws ClientProtocolException, IOException {  
  171.   return doSendBase(urlpath, method, StringToHttpEntity(params, charset),  
  172.     charset, isAutoRedirect, isCloseConn);  
  173. }  
  174.   
  175. /** 
  176.   * 取得網頁內容 
  177.   *  
  178.   * @param urlpath 
  179.   *            網址 
  180.   * @param method 
  181.   *            Method.get or Method.post 
  182.   * @param params 
  183.   *            參數 
  184.   * @param charset 
  185.   *            編碼,如HTTP.UTF_8 
  186.   * @param isAutoRedirect 
  187.   *            如果網頁回應狀態為轉導到新網頁,且Header的location有值,則自己以location所指網址取得內容 
  188.   * @param isCloseConn 
  189.   *            是否關閉連線 
  190.   * @return 失敗回傳null,成功回傳網頁HTML 
  191.   * @throws ClientProtocolException 
  192.   * @throws IOException 
  193.   */  
  194. public String doSend(String urlpath, Method method,  
  195.    List params, String charset, boolean isAutoRedirect,  
  196.    boolean isCloseConn) throws ClientProtocolException, IOException {  
  197.   return doSendBase(urlpath, method, ListToHttpEntity(params, charset),  
  198.     charset, isAutoRedirect, isCloseConn);  
  199. }  
  200.   
  201. /** 
  202.   * 取得網頁內容 
  203.   *  
  204.   * @param urlpath 
  205.   *            網址 
  206.   * @param method 
  207.   *            Method.get or Method.post 
  208.   * @param params 
  209.   *            參數 
  210.   * @param charset 
  211.   *            編碼,如HTTP.UTF_8 
  212.   * @param isAutoRedirect 
  213.   *            如果網頁回應狀態為轉導到新網頁,且Header的location有值,則自己以location所指網址取得內容 
  214.   * @param isCloseConn 
  215.   *            是否關閉連線 
  216.   * @return 失敗回傳null,成功回傳網頁HTML 
  217.   * @throws ClientProtocolException 
  218.   * @throws IOException 
  219.   */  
  220. public String doSend(String urlpath, Method method,  
  221.    HashMap params, String charset,  
  222.    boolean isAutoRedirect, boolean isCloseConn)  
  223.    throws ClientProtocolException, IOException {  
  224.   return doSendBase(urlpath, method,  
  225.     HashMapToHttpEntity(params, charset), charset, isAutoRedirect,  
  226.     isCloseConn);  
  227. }  
  228.   
  229. /** 
  230.   * 取得網頁內容 
  231.   *  
  232.   * @param urlpath 
  233.   *            網址 
  234.   * @param method 
  235.   *            Method.get or Method.post 
  236.   * @param params 
  237.   *            參數 
  238.   * @param charset 
  239.   *            編碼,如HTTP.UTF_8 
  240.   * @param isAutoRedirect 
  241.   *            如果網頁回應狀態為轉導到新網頁,且Header的location有值,則自己以location所指網址取得內容 
  242.   * @param isCloseConn 
  243.   *            是否關閉連線 
  244.   * @return 失敗回傳null,成功回傳網頁HTML 
  245.   * @throws ClientProtocolException 
  246.   * @throws IOException 
  247.   */  
  248. public String doSendBase(String urlpath, Method method, HttpEntity params,  
  249.    String charset, boolean isAutoRedirect, boolean isCloseConn)  
  250.    throws ClientProtocolException, IOException {  
  251.   String responseBody = null;  
  252.   HttpUriRequest httpgetpost = null;  
  253.   
  254.   statuscode = HttpStatus.SC_NO_CONTENT;  
  255.   try {  
  256.    if (httpclient == null || isClosedConn())  
  257.     httpclient = new DefaultHttpClient();  
  258.   
  259.    if (proxy != null)  
  260.     httpclient.getParams().setParameter(  
  261.       ConnRoutePNames.DEFAULT_PROXY, proxy);  
  262.   
  263.    if (method == Method.post) {  
  264.     httpgetpost = new HttpPost(urlpath);  
  265.     if (params != null) {  
  266.      ((HttpPost) httpgetpost).setEntity(params);  
  267.     }  
  268.    } else {  
  269.     if (params != null) {  
  270.      urlpath += "?"  
  271.        + inputStream2String(params.getContent(), charset);  
  272.     }  
  273.     httpgetpost = new HttpGet(urlpath);  
  274.    }  
  275.   
  276.    HttpResponse response = httpclient.execute(httpgetpost);  
  277.    statuscode = response.getStatusLine().getStatusCode();  
  278.    if ((statuscode == HttpStatus.SC_MOVED_TEMPORARILY)  
  279.      || (statuscode == HttpStatus.SC_MOVED_PERMANENTLY)  
  280.      || (statuscode == HttpStatus.SC_SEE_OTHER)  
  281.      || (statuscode == HttpStatus.SC_TEMPORARY_REDIRECT)) {  
  282.     Header header = response.getFirstHeader("location");  
  283.   
  284.     if (header != null) {  
  285.      newuri = header.getValue();  
  286.      if ((newuri == null) || (newuri.equals("")))  
  287.       newuri = "/";  
  288.      if (isAutoRedirect) {  
  289.       httpgetpost.abort();  
  290.       httpgetpost = null;  
  291.       responseBody = doSendBase(newuri, Method.get, null,  
  292.         charset, truefalse);  
  293.      }  
  294.     }  
  295.    } else if (statuscode == HttpStatus.SC_OK) {  
  296.     responseBody = inputStream2String(response.getEntity()  
  297.       .getContent(), charset);  
  298.    }  
  299.   } catch (ClientProtocolException e) {  
  300.    throw e;  
  301.   } catch (IOException e) {  
  302.    throw e;  
  303.   } catch (Exception e) {  
  304.    e.printStackTrace();  
  305.   } finally {  
  306.    if (httpgetpost != null) {  
  307.     httpgetpost.abort();  
  308.     httpgetpost = null;  
  309.    }  
  310.    closeConn(isCloseConn);  
  311.   }  
  312.   return responseBody;  
  313. }  
  314.   
  315. /** 
  316.   * 將inputStream轉為String 
  317.   *  
  318.   * @param is 
  319.   *            inputStream 
  320.   * @param charset 
  321.   *            編碼,如HTTP.UTF_8 
  322.   * @return inputStream的內容 
  323.   * @throws UnsupportedEncodingException 
  324.   */  
  325. public static String inputStream2String(InputStream is, String charset)  
  326.    throws UnsupportedEncodingException {  
  327.   BufferedReader in = new BufferedReader(new InputStreamReader(is,  
  328.     charset));  
  329.   StringBuffer buffer = new StringBuffer();  
  330.   String line = "";  
  331.   try {  
  332.    boolean isfirst = true;  
  333.    while ((line = in.readLine()) != null) {  
  334.     if (!isfirst) {  
  335.      buffer.append("\n");  
  336.     } else {  
  337.      isfirst = false;  
  338.     }  
  339.     buffer.append(line);  
  340.    }  
  341.   } catch (IOException e) {  
  342.    e.printStackTrace();  
  343.   }  
  344.   
  345.   return buffer.toString();  
  346. }  
  347.   
  348. /** 
  349.   * List轉為HttpEntity 
  350.   *  
  351.   * @param nvps 
  352.   * @param charset 
  353.   *            編碼,如HTTP.UTF_8 
  354.   * @return 
  355.   * @throws UnsupportedEncodingException 
  356.   */  
  357. public static HttpEntity ListToHttpEntity(List nvps,  
  358.    String charset) throws UnsupportedEncodingException {  
  359.   HttpEntity result = null;  
  360.   if (nvps != null && nvps.size() > 0) {  
  361.    result = new UrlEncodedFormEntity(nvps, charset);  
  362.   
  363.   }  
  364.   return result;  
  365. }  
  366.   
  367. /** 
  368.   * String to HttpEntity( 
  369.   *  
  370.   * @param nvps 
  371.   * @param charset 
  372.   *            編碼,如HTTP.UTF_8 
  373.   * @return 
  374.   * @throws UnsupportedEncodingException 
  375.   */  
  376. public static HttpEntity StringToHttpEntity(String nvps, String charset)  
  377.    throws UnsupportedEncodingException {  
  378.   HttpEntity result = null;  
  379.   if (nvps != null) {  
  380.    StringEntity reqEntity = new StringEntity(nvps, charset);  
  381.    reqEntity.setContentType("application/x-www-form-urlencoded");  
  382.    result = reqEntity;  
  383.   }  
  384.   return result;  
  385. }  
  386.   
  387. /** 
  388.   * HashMap To HttpEntity 
  389.   *  
  390.   * @param nvps 
  391.   * @param charset 
  392.   *            編碼,如HTTP.UTF_8 
  393.   * @return 
  394.   * @throws UnsupportedEncodingException 
  395.   */  
  396. public static HttpEntity HashMapToHttpEntity(HashMap nvps,  
  397.    String charset) throws UnsupportedEncodingException {  
  398.   HttpEntity result = null;  
  399.   if (nvps != null) {  
  400.    result = new StringEntity(hashMapToString(nvps, charset), charset);  
  401.    try {  
  402.     result = StringToHttpEntity(inputStream2String(result  
  403.       .getContent(), charset), charset);  
  404.    } catch (IllegalStateException e) {  
  405.     e.printStackTrace();  
  406.    } catch (IOException e) {  
  407.     e.printStackTrace();  
  408.    }  
  409.   }  
  410.   return result;  
  411. }  
  412.   
  413. /** 
  414.   * hashMapToString 
  415.   *  
  416.   * @param map 
  417.   * @param charset編碼 
  418.   *            ,如HTTP.UTF_8 
  419.   * @return 
  420.   * @throws UnsupportedEncodingException 
  421.   */  
  422. @SuppressWarnings("unchecked")  
  423. public static String hashMapToString(HashMap map,  
  424.    String charset) throws UnsupportedEncodingException {  
  425.   StringBuffer result = new StringBuffer();  
  426.   java.util.Iterator it = map.entrySet().iterator();  
  427.   boolean isfirst = true;  
  428.   while (it.hasNext()) {  
  429.    java.util.Map.Entry entry = (java.util.Map.Entry) it.next();  
  430.    if (isfirst) {  
  431.     isfirst = false;  
  432.    } else {  
  433.     result.append("&");  
  434.    }  
  435.    result  
  436.      .append(URLEncoder.encode(entry.getKey().toString(),  
  437.        charset));  
  438.    result.append("=");  
  439.    result.append(URLEncoder.encode(entry.getValue().toString(),  
  440.      charset));  
  441.   }  
  442.   return result.toString();  
  443. }  
  444.   
  445. public static ArrayList paramToArray(String param)  
  446.    throws UnsupportedEncodingException {  
  447.   ArrayList arr = null;  
  448.   if(param!=null){  
  449.       String[] p = param.split("&");  
  450.       if (param.toLowerCase().contains("&")) {  
  451.        ArrayList p2 = new ArrayList();  
  452.        int j = 0;  
  453.        for (int i = 0; i < p.length; i++) {  
  454.         if (p[i].toLowerCase().startsWith("amp;")) {  
  455.          p2.set(j - 1, p2.get(j - 1) + "&" + p[i].substring(4));  
  456.          j--;  
  457.         }  
  458.         p2.add(p[i]);  
  459.         j++;  
  460.        }  
  461.        p2.toArray(p);  
  462.       }  
  463.   
  464.       for (int i = 0; i < p.length; i++) {  
  465.        String[] item = p[i].split("=");  
  466.        if (item.length == 2) {  
  467.         if (arr == null)  
  468.          arr = new ArrayList();  
  469.         // item[0]=URLDecoder.decode(item[0],charset);  
  470.         // item[1]=URLDecoder.decode(item[1],charset);  
  471.         arr.add(item);  
  472.        }  
  473.       }  
  474.   }  
  475.   return arr;  
  476. }  
  477. }  

- 測試 Http GET 的範例代碼 :
  1. public void testDoGet() {  
  2.   String urltest = "http://www.google.com.tw" ;  
  3.   String charset="UTF-8";  
  4.   HTTPBaseIO.Method method = HTTPBaseIO.Method.get;  
  5.   HTTPBaseIO reqClient = new HTTPBaseIO();  
  6.   try {  
  7.    String html=reqClient.doSendBase(urltest,method, null,charset,falsefalse);  
  8.    System.out.println(html);  
  9.    if(html==null) System.out.println("Client get nothing");  
  10.   } catch (Exception e) {  
  11.    e.printStackTrace();  
  12.   } finally {  
  13.    reqClient.closeConn();  
  14.   }  
  15. }  

執行結果 :
取得 Google 首頁的 html 代碼.
This message was edited 1 time. Last update was at 03/09/2010 18:42:39

沒有留言:

張貼留言

網誌存檔

關於我自己

我的相片
Where there is a will, there is a way!