1. 程式人生 > >Java Http請求工具類和接收請求的方法

Java Http請求工具類和接收請求的方法

表面現像上面看看GET和POST的區別:

1.GET請求的資料會附在URL之後(就是把資料放置在HTTP協議頭中),以?分割URL和傳輸資料,引數之間以&相連,如:login.action?name=hyddd&password=idontknow&verify=%E4%BD%A0%E5%A5%BD。如果資料是英文字母/數字,原樣傳送,如果是空格,轉換為+,如果是中文/其他字元,則直接把字串用BASE64加密,得出如:%E4%BD%A0%E5%A5%BD,其中%XX中的XX為該符號以16進製表示的ASCII。

POST把提交的資料則放置在是HTTP包的包體中。

2."GET方式提交的資料最多隻能是1024位元組,理論上POST沒有限制,可傳較大量的資料,IIS4中最大為80KB,IIS5中為100KB"??!
 以上這句是我從其他文章轉過來的,其實這樣說是錯誤的,不準確的:

(1).首先是"GET方式提交的資料最多隻能是1024位元組",因為GET是通過URL提交資料,那麼GET可提交的資料量就跟URL的長度有直接關係了。 而實際上,URL不存在引數上限的問題,HTTP協議規範沒有對URL長度進行限制。這個限制是特定的瀏覽器及伺服器對它的限制。
IE對URL長度的限制是 2083位元組(2K+35)。對於其他瀏覽器,如Netscape、FireFox等,理論上沒有長度限制,其限制取決於作業系統的支援。
(2).理論上講,POST是沒有大小限制的,HTTP協議規範也沒有進行大小限制,說“POST資料量存在80K/100K的大小限制”是不準確的,POST資料是沒有限制 的,起限制作用的是伺服器的處理程式的處理能力。對於ASP程式,Request物件處理每個表單域時存在100K的資料長度限制。但如果使用 Request.BinaryRead則沒有這個限制。   由這個延伸出去,對於IIS 6.0,微軟出於安全考慮,加大了限制。我們還需要注意:
     1).IIS 6.0預設ASP POST資料量最大為200KB,每個表單域限制是100KB。
     2).IIS 6.0預設上傳檔案的最大大小是4MB。
     3).IIS 6.0預設最大請求頭是16KB。
    IIS 6.0之前沒有這些限制。[具體參考
http://blog.csdn.net/somat/article/details/158707
]
所以上面的80K,100K可能只是預設值而已(注:關於IIS4和IIS5的引數,我還沒有確認),但肯定是可以自己設定的。

由於每個版本的IIS對這些引數的預設值都不一樣,具體請參考相關的IIS配置文件。

此HTTPUtil工具類主要介紹怎麼傳送HTTP請求並附上獲取請求引數的兩種方式

import com.yjbq.common.StringUtil;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.util.Map;

public class HttpUtil {

    private HttpUtil() {
    }

    /**
     * 傳送GET請求
     *
     * @param url 傳送請求的URL
     * @param queryParas 引數集合
     * @return
     */
    public static String get(String url, Map<String, String> queryParas) {
        return get(url, queryParas, null);
    }

    /**
     * 傳送GET請求
     *
     * @param url 傳送請求的URL
     * @return 所代表遠端資源的響應結果
     */
    public static String get(String url) {
        return get(url, null, null);
    }

    /**
     * 傳送GET請求
     *
     * @param url 傳送請求的URL
     * @param queryParas 引數集合
     * @param headers 頭集合
     * @return 所代表遠端資源的響應結果
     */
    public static String get(String url, Map<String, String> queryParas, Map<String, String> headers) {
        HttpURLConnection conn = null;
        try {
             //獲取HttpURLConnection連線並設定引數
            conn = getHttpConnection(buildUrlWithQueryString(url, queryParas), "GET", headers);
             // 建立HttpURLConnection實際的連線
            conn.connect();
            //返回  定義BufferedReader輸入流來讀取URL的響應
            return readResponseString(conn);
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            if (conn != null) {
                conn.disconnect();
            }
        }
    }

    /**
     * 傳送POST請求
     *
     * @param url 傳送請求的URL
     * @param data http請求包的包體
     * @param headers 頭集合
     * @return 所代表遠端資源的響應結果
     */
    public static String post(String url, String data, Map<String, String> headers) {
        return post(url, null, data, headers);
    }

    /**
     * 傳送POST請求
     *
     * @param url 傳送請求的URL
     * @param queryParas 請求引數(寫在url後面的引數)如http://www.baidu.com?state=1&data=233
     * @param data http請求包的包體
     * @param headers 頭集合
     * @return
     */
    public static String post(String url, Map<String, String> queryParas, String data, Map<String, String> headers) {
        HttpURLConnection conn = null;
        try {
            //獲取HttpURLConnection連線並設定引數
            conn = getHttpConnection(buildUrlWithQueryString(url, queryParas), "POST", headers);
            // 建立HttpURLConnection實際的連線
            conn.connect();
            // 獲取URLConnection物件對應的輸出流
            OutputStream out = conn.getOutputStream();
            // 傳送請求引數
            out.write(data.getBytes("utf-8"));
            // flush輸出流的緩衝
            out.flush();
            //關閉輸出流
            out.close();
            //返回  定義BufferedReader輸入流來讀取URL的響應
            return readResponseString(conn);
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            if (conn != null) {
                conn.disconnect();
            }
        }
    }

    /**
     * 獲取HttpURLConnection連線並設定引數
     *
     * @param url     傳送請求的URL
     * @param method 請求方式(POST/GET)
     * @param headers 請求頭
     * @return  所代表遠端資源的響應結果
     * @throws IOException
     * @throws NoSuchAlgorithmException
     * @throws NoSuchProviderException
     * @throws KeyManagementException
     */
    private static HttpURLConnection getHttpConnection(String url, String method, Map<String, String> headers) throws IOException, NoSuchAlgorithmException, NoSuchProviderException, KeyManagementException {
        //將url轉變為URL物件
        URL _url = new URL(url);
        //開啟URL連線
        HttpURLConnection conn = (HttpURLConnection) _url.openConnection();
        //設定請求方式
        conn.setRequestMethod(method);
        // 傳送POST請求必須設定如下兩行
        conn.setDoOutput(true);
        conn.setDoInput(true);
        
        //連線時長
        conn.setConnectTimeout(20000);
        //讀取時長
        conn.setReadTimeout(60000);

        // 設定通用的請求屬性
        conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
        conn.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.146 Safari/537.36");
      
        if (headers != null && !headers.isEmpty()) {
            for (Map.Entry<String, String> entry : headers.entrySet()) {
                conn.setRequestProperty(entry.getKey(), entry.getValue());
            }
        }
        return conn;
    }

    /**
     * 將引數和URL地址拼接
     *
     * @param url  傳送請求的URL如http://www.baidu.com {"state":"1","data":"拼接Url"}
     * @param queryParas 傳遞的引數
     * @return
     */
    private static String buildUrlWithQueryString(String url, Map<String, String> queryParas) {
        if (queryParas == null || queryParas.isEmpty()) {
            return url;
        }

        StringBuilder sb = new StringBuilder(url);
        boolean isFirst;
        //判斷URL是否有 ?
        if (url.indexOf("?") == -1) {
            isFirst = true;
            sb.append("?");
        } else {
            isFirst = false;
        }
        //遍歷請求引數
        for (Map.Entry<String, String> entry : queryParas.entrySet()) {
            if (isFirst) {
                isFirst = false;
            } else {
                sb.append("&");
            }

            String key = entry.getKey();
            String value = entry.getValue();
            if (!StringUtil.isNull(value)) {
                //對value進行轉碼
                try {
                    value = URLEncoder.encode(value, "utf-8");
                } catch (UnsupportedEncodingException e) {
                    throw new RuntimeException(e);
                }
            }
            sb.append(key).append("=").append(value);
        }
        return sb.toString();
    }

    /**
     * 讀取URL的響應
     *
     * @param conn HttpURLConnection物件
     * @return
     */
    private static String readResponseString(HttpURLConnection conn) {
        StringBuilder sb = new StringBuilder();
        InputStream inputStream = null;
        try {
            //獲取響應內容
            inputStream = conn.getInputStream();
            // 定義BufferedReader輸入流來讀取URL的響應
            BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, "utf-8"));
            String line;
            while ((line = reader.readLine()) != null) {
                sb.append(line).append("\n");
            }
            return sb.toString();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        // 使用finally塊來關閉輸入流
        finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                }
            }
        }
    }
}

測試類HttpTest中getRequestData()方法提供了獲取引數的兩種方式具體見程式碼(此程式碼用的是JFinal框架繼承了JFinal的Controller)並用到了fastjson-1.2.6.jar包。

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.jfinal.core.Controller;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.ServletInputStream;

/**
 *
 * @author Administrator
 */
public class HttpTest extends Controller{
    public void getTest(){
        try {
            String s = getRequestData();
            System.out.println(s);
            JSONObject json = JSONObject.parseObject(s);
            System.out.println(json.getString("test"));
            renderJson(s);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
    
    /**
     * 獲取GET/POST請求提交的資料
     * @return 
     */
    public String getRequestData(){
        StringBuilder sb = new StringBuilder();
        try{
            //獲取Http請求包的包體有兩種方式getInputStream()、getReader(),因為GET方式請求一般不包含包體.一般用於POST請求獲取引數.
            BufferedReader br = new BufferedReader(new InputStreamReader(getRequest().getInputStream()));
            //BufferedReader br = new BufferedReader(getRequest().getReader());
            String line;
            while((line = br.readLine())!=null){
                sb.append(line);
            }
        }catch(IOException e){
            System.out.println("getPostData Error: " + e.getLocalizedMessage());
            e.printStackTrace();
        }
        //如果包體沒有值則獲取url後面的引數
        if(sb.length() != 0){
            return sb.toString();
        }else{
            JSONObject json = new JSONObject();
            //JFinal獲取url引數的方法
            Enumeration<String> names = getRequest().getParameterNames();
            //遍歷引數
            while(names.hasMoreElements()){
                String key = names.nextElement();
                json.put(key, getPara(key));
            }
            return json.toString();
        }
    }
    
    public static void main(String[] args){
        Map<String, String> params = new HashMap<String, String>();
        params.put("num", "201");
        params.put("name", "李明");
        params.put("phone", "176****1828");

        Map<String, String> headers = new HashMap<String, String>();
        headers.put("Content-Type", "application/json;charset=UTF-8");
        //請求引數附在URL後面的請求方式
        //String result = HttpUtil.post("http://地址:埠/httpTest/getTest", params, "", headers);
        //請求引數放在HTTP包的包體中
        String result = HttpUtil.post("http://地址:埠/httpTest/getTest",JSON.toJSONString(params),headers);
        System.out.println(result);
    }
}