本節摘要:之前介紹過采用httpclient發送get和post請求到http服務器端,那么我們不用這個插件是否也可以正常的用get/post方式發送http請求到http服務端呢?畢竟用這個插件要下載,還要去看一大推的API,不是那么的方便,那么,咱們就用JDK自帶的URL類和HttpURLConnection類來完成get/post方式的HTTP請求。
要查看基於httpclient的方式發送http請求,請查看之前的博客:http://www.cnblogs.com/java-pan/archive/2012/02/26/httpclient-post-get.html
本節比較簡單,就不在和之前的博客一樣,按一條一條的來寫。
場景介紹:
項目中采用http+json的方法訪問http服務,客戶端發送二進制數據給http服務器端,http服務器端收到請求后,先把二進制數據轉換為json字符串,然后再去做一推的邏輯處理,最后把處理的結果以json格式的字符串返回給客戶端。
HTTP服務器端----服務端采用的是servlet來寫的一個http服務,這里只貼出服務器端接收到二進制數據並且轉換為json字符串的代碼
HTTP服務端
1 /** 2 * 獲取二進制的報文體,並轉換成字符串 3 */ 4 public String getContext(HttpServletRequest request) throws ServletException, IOException { 5 byte[] buffer = new byte[64*1024]; 6 7 InputStream in = request.getInputStream(); 8 int length = in.read(buffer); 9 String encode = request.getCharacterEncoding(); 10 11 byte[] data = new byte[length]; 12 System.arraycopy(buffer, 0, data, 0, length); 13 String context = new String(data, encode); 14 15 return context; 16 }
HTTP客戶端----先拼裝json字符串,然后轉換為二進制數據流發送http請求。拼裝json字符串采用jsonobject插件來實現,這里就不貼出來了。
HTTP客戶端
1 /** 2 * 發送請求到http服務然后接收返回報文 3 * @param jsonStr 請求的json格式的字符串 4 * @param path 請求的http服務的路徑 5 * @return 返回請求的響應信息 6 * @throws IOException 7 */ 8 public static String channelchange2(String jsonStr, String path) 9 throws IOException { 10 // 得到請求報文的二進制數據 11 byte[] data = jsonStr.getBytes(); 12 java.net.URL url = new java.net.URL(path); 13 //openConnection() 返回一個 URLConnection 對象,它表示到 URL 所引用的遠程對象的連接 14 java.net.HttpURLConnection conn = (java.net.HttpURLConnection) url.openConnection();// 打開一個連接 15 conn.setRequestMethod("POST");// 設置post方式請求 16 conn.setConnectTimeout(5 * 1000);// 設置連接超時時間為5秒 JDK1.5以上才有此方法 17 conn.setReadTimeout(20 * 1000);// 設置讀取超時時間為20秒 JDK1.5以上才有此方法 18 // 打算使用 URL 連接進行輸出,則將 DoOutput 標志設置為 true 19 conn.setDoOutput(true); 20 // 這里只設置內容類型與內容長度的頭字段根據傳送內容決定 21 // 內容類型Content-Type: 22 // application/x-www-form-urlencoded、text/xml;charset=GBK 23 // 內容長度Content-Length: 38 24 conn.setRequestProperty("Content-Type", "text/xml;charset=GBK"); 25 conn.setRequestProperty("Content-Length", String.valueOf(data.length)); 26 OutputStream outStream = conn.getOutputStream();// 返回寫入到此連接的輸出流 27 // 把二進制數據寫入是輸出流 28 outStream.write(data); 29 // 內存中的數據刷入 30 outStream.flush(); 31 //關閉流 32 outStream.close(); 33 34 String msg = "";// 保存調用http服務后的響應信息 35 // 如果請求響應碼是200,則表示成功 36 if (conn.getResponseCode() == 200) { 37 // HTTP服務端返回的編碼是UTF-8,故必須設置為UTF-8,保持編碼統一,否則會出現中文亂碼 38 BufferedReader in = new BufferedReader(new InputStreamReader( 39 (InputStream) conn.getInputStream(), "UTF-8"));//返回從此打開的連接讀取的輸入流 40 msg = in.readLine(); 41 in.close(); 42 } 43 conn.disconnect();// 斷開連接 44 return msg; 45 }
說明:
1.因為我們項目組是寫服務端,客戶端不需要我們寫,我只是寫了一個客戶端來模擬http服務端的調用,故對異常只是拋出,實際中應該捕獲住這些異常,比如無法連接到指定的服務,讀取數據超時,請求響應失敗(200表示響應成功)等等。
2.在處理的過程中遇到的一個大的問題就是請求和輸出報文的中文問題。
對於請求報文,只要是請求頭部和請求內容字段編碼統一,服務器端就可以正常的接受,客戶端字符串jsonStr編碼是GBK,請求頭設置為GBK,已經驗證服務器端可以正常接受。
對於輸出報文,服務器端采用UTF-8的形式輸出,客戶端也采用UTF-8的形式接受,也已經通過驗證,客戶端可以正常接受服務器端返回的中文。
3.關於java.net.URL和java.net.HttpURLConnection類的介紹請查看JDK的API,本客戶端基於JDK1.5開發。
4.客戶端和服務器端未寫明導入類的路徑的類,都是普通的java I/O類,此種方式請求http服務端沒有采用任何的插件。
5.如果不設置請求頭的編碼,服務端在下面的一句代碼會報空指針異常
String context = new String(data, encode);
6.關於get方法的請求,這里就不列出來了。只是把post改為get而已。
哪位大俠理解的比較深入的,可以說說httpclient請求和此種請求有什么區別?用的時候要怎么來選擇呢?
