摘要
看完本文可以知道,使用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.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; }
#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解析和文件上傳下次再寫個專題