java學習-get和post請求


摘要
  看完本文可以知道,使用java原生編寫get/post請求的步驟,進行網絡請求時應該注意的地方。
  這里使用java自帶的HttpUrlConnection對象進行網絡請求,
  請求步驟大致分為五步
  1、創建URL對象
  2、打開URL連接
  3、設置通用屬性
  4、建立實際的連接
  5、讀取返回的內容
 
正文
 
http網絡請求中比較常用的請求方式有get和post請求,其它的如head, put, 以及自定義的OPTIONS等請求方式在這里不做討論
 
java中使用的請求對象一般是HttpUrlConnection,
其它框架封裝的如httpClient,這個apache CommonsHttpClient項目已經不再被維護,隨着java版本的更新,這個工具不推薦再使用了,
而其他了,如okhttp,Retrofit2等網絡請求框架主要使用於android端的網絡請求,
在服務器端進行網絡請求使用自己簡單封裝的http工具類即可。
 
我們請求的地址需要使用URL對象將字符串地址進行封裝
即URL connURL = new URL("http://www.xxxx./")
網絡請求的步驟
#GET請求
 
    首先要對請求的參數進行中文編碼
     java.net.URLEncoder.encode(parameters.get(name),
                                    "UTF-8")
    否則服務器接收到的中文數據會變成亂碼,這是人為的錯誤。
    將編碼的參數和url進行拼接形成真正的請求地址
String url = url + "?" + params
    1、創建URL對象
URL connURL = new URL("http://www.xxxx./")

 

    2、打開url鏈接獲得HttpUrlConnection
HttpURLConnection httpConn = (HttpURLConnection) connURL.openConnection();

     3、設置通用的屬性,  ----請求頭部信息
       也就是模仿瀏覽器的請求頭部的信息
         Connection、Accept、User-Agent、Cookie 等其它的請求頭header信息
httpConn.setRequestProperty("Accept", "*/*");
  Connection:表示是否需要持久鏈接值為“Keep-Alive   ,持久鏈接可以減少下載的時間,但服務器必須要返回響應頭Content-Length,返回內容的長度。
        http的socket,要經過三次握手通信才能確保連接可用,
 
http連接的兩種方式:串行連接,持久連接
持久連接的實現方式有兩種:HTTP/1.0+的請求頭Connection:keep-alive與HTTP/1.1的持久連接
 
串行連接:1、打開連接
          2、請求
          3、處理
          4、響應
          5、關閉連接
          重復上面步驟

持久連接:1、打開連接
          2、請求
          3、處理
          4、響應
          第二次直接到2操作,
          發送請求
持久連接第一次請求后不會關閉連接,下次再發送請求時就不需要再建立連接了

 參考資料

Http持久連接與HttpClient連接池

     
其實就是減少了http請求時四次握手(關閉連接1次握手)的時間,
      HTTP 1.1默認進行持久連接
        
    4、 建立連接
        
httpConn.connect();
    5、 獲取響應頭部的信息 ,這個步驟可以省略
httpConn.getHeaderField("keyName");
  這里主要是獲取到cookie的信息,以便下次訪問時不再需要登錄,直接通過cookie獲取數據
  (當然,隨着各大網站的特意防御,只獲取到cookie,下次攜帶cookie可能會被攔截,即不能抓取到想要的數據)
    
如果要對response的響應頭部的所有信息進行遍歷,則代碼如下
// 響應頭部獲取
            Map<String, List<String>> headers = httpConn.getHeaderFields();
           
            // 遍歷所有的響應頭字段
            for (String key : headers.keySet()) {
              
                  System.out.println(key+":  "+httpConn.getHeaderField(key));
            }

這是模擬訪問www.baidu.com返回的response頭部信息

 

 
6、讀取響應的內容,網頁html文件,或者特定的返回值數據
// 定義BufferedReader輸入流來讀取URL的響應,並設置編碼方式
    BufferedReader in= null;

            in = new BufferedReader(new InputStreamReader(httpConn
                    .getInputStream(), "UTF-8"));//通用編碼格式為utf-8
            String line;
            // 讀取返回的內容
            while ((line = in.readLine()) != null) {
                result += line;
            }
            httpConn.disconnect();//主動斷開httpConn連接
還有需要關閉,字符輸入流BufferedReader
這個需要在finally塊中進行關閉
finally{
    try {
         if (in != null) {
            in.close();
         }
     } catch (IOException ex) {
           ex.printStackTrace();
      }
}

 

上面是一個get請求的正常流程,當然其中的讀取內容的方式有很多種,有些可以直接保存在電腦的文件中,這些方式先不考慮

 

一個get請求需要注意的幾點:

  • 請求參數,中文,其它的轉義符號需要進行編碼
如下代碼,中文和特殊意義字符都會被進行編碼,而英語字母則不需要編碼
     String url = "http://www.baidu.com";
        String ss="你是逗逼嗎";
        try {
            System.out.println(java.net.URLEncoder.encode(url,"UTF-8"));
            System.out.println(java.net.URLEncoder.encode(ss,"UTF-8"));
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }

輸出結果:

  

 

  • get請求頭部最好設置個代理,否則有可能被網站給攔截,拒接訪問

,如這里設置為火狐瀏覽器,模擬瀏覽器的請求頭即可

httpConn.setRequestProperty("User-Agent",
                    "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1)");
  • 連接斷開時候記得一定要把輸入輸出流給關掉,降低異常出現

  如上面的HttpUrlConnection連接,還有bufferReader對象

一個完整的get請求代碼

    public static String sendGet(String url, LinkedHashMap<String, String> parameters) {
        String result = "";// 返回的結果
        BufferedReader in = null;// 讀取響應輸入流
        StringBuffer sb = new StringBuffer();// 存儲參數
        String params = "";// 編碼之后的參數
        try {
            // 編碼請求參數
            if (parameters.size() == 1) {
                for (String name : parameters.keySet()) {
                    sb.append(name).append("=").append(
                            java.net.URLEncoder.encode(parameters.get(name),
                                    "UTF-8"));
                }
                params = sb.toString();
            } else {
                for (String name : parameters.keySet()) {
                    sb.append(name).append("=").append(
                            java.net.URLEncoder.encode(parameters.get(name),
                                    "UTF-8")).append("&");
                }
                String temp_params = sb.toString();
                params = temp_params.substring(0, temp_params.length() - 1);
            }
            String full_url = url + "?" + params;
            // 創建URL對象
            URL connURL = new URL(full_url);
            // 打開URL連接
            HttpURLConnection httpConn = (HttpURLConnection) connURL
                    .openConnection();
            // 設置通用屬性
            httpConn.setRequestProperty("Accept", "*/*");
            httpConn.setRequestProperty("Connection", "Keep-Alive");
            httpConn.setRequestProperty("User-Agent",
                    "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1)");
            // 建立實際的連接
            httpConn.connect();
            // 響應頭部獲取
            Map<String, List<String>> headers = httpConn.getHeaderFields();
            
            // 遍歷所有的響應頭字段
            for (String key : headers.keySet()) {
                //System.out.println(key+":  "+httpConn.getHeaderField(key));
            }
            // 定義BufferedReader輸入流來讀取URL的響應,並設置編碼方式
            in = new BufferedReader(new InputStreamReader(httpConn
                    .getInputStream(), "GBK"));
            String line;
            // 讀取返回的內容
            while ((line = in.readLine()) != null) {
                result += line;
            }
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("Http請求方法內部問題");
        } finally {
            try {
                if (in != null) {
                    in.close();
                }
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
        return result;
    }
View Code

 

#POST網絡請求方式
 post請求跟get請求的方式大體流程一樣,區別在於傳遞請求數據的方式不一樣,post可以提交的數據大小沒有限制,
  而get請求理論上沒有大小限制,由於瀏覽器限制其長度,所以傳遞數據大小有限制
post請求不需要設置請求頭的user-agent
如果要避免登陸,則需要將登陸時返回的請求頭中cookie信息在httpUrlConnect中設置請求投信息即可
connection.setRequestProperty("Cookie", "這里放cookie數據");
connection.setRequestProperty("Content-Type",
                    "application/x-www-form-urlencoded;charset=utf-8");
content-type主要進行設置服務器解析數據的方式,服務器會通過請求頭的值將body里面的數據以鍵值對key  value方式進行解析,
我們在后台只需要用request.getParameter("keyName")就可以將數據讀取出來
其它提交數據的格式:
  • multipart/form-data類型主要是上傳文件時用到;
  • application/x-www-form-urlencoded類型主要是提交k-v時用到,當然這種方法也可以將json設置在v中提交json數據;
  • application/json類型主要是傳遞json數據用到,層次比較深的數據;
public static String sendPost(String curl, String param) {
        String result = "";// 返回的結果
        BufferedReader in = null;// 讀取響應輸入流
        try {
            //創建連接
            URL url = new URL(curl);
            HttpURLConnection connection = (HttpURLConnection) url
                    .openConnection();
            connection.setDoOutput(true); 是否打開outputStream 相對於程序,即我們向遠程服務器寫入數據,默認為false,不打開
            connection.setDoInput(true);  輸入流,獲取到返回的響應內容, 默認為true,所以get請求時可以不設置這個連接信息 
            connection.setRequestMethod("POST"); //發送請求的方式
            connection.setUseCaches(false); //不使用緩存
            connection.setInstanceFollowRedirects(true); //重定向,一般瀏覽器才需要
            connection.setRequestProperty("Content-Type",
                    "application/x-www-form-urlencoded;charset=utf-8"); //設置服務器解析數據的方式

            connection.connect();

            //POST請求
            BufferedWriter out = new BufferedWriter(new OutputStreamWriter(connection.getOutputStream(),"UTF-8"));
            out.write(param);
            out.flush();
            out.close();

            //讀取響應
            // 定義BufferedReader輸入流來讀取URL的響應,並設置編碼方式
            in = new BufferedReader(new InputStreamReader(connection.getInputStream(), "UTF-8"));
            String line;
            // 讀取返回的內容
            while ((line = in.readLine()) != null) {
                result += line;
            }
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("Http請求方法內部問題");
        } finally {
            try {
                if (in != null) {
                    in.close();
                }
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
        return result;
    }

post請求不同提交數據方式有對應的解析方法,json解析和文件上傳下次再寫個專題

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM