Android使用HttpUrlConnection請求伺服器傳送資料詳解
在Java中可以使用HttpURLConnection發起這兩種請求,瞭解此類,對於瞭解soap,和編寫servlet的自動測試程式碼都有很大的幫助。
一、那麼我們先來看看用HttpUrlConnection怎樣用Post發起請求傳輸json資料(這裡以常用的json作為示例):
public void httpUrlConnPost(String name,String password){ HttpURLConnection urlConnection = null; URL url = null; try { url = new URL("http://192.168.1.105:8080/KYDServer/servlet/Login"); urlConnection = (HttpURLConnection) url.openConnection();//開啟http連線 urlConnection.setConnectTimeout(3000);//連線的超時時間 urlConnection.setUseCaches(false);//不使用快取 //urlConnection.setFollowRedirects(false);是static函式,作用於所有的URLConnection物件。 urlConnection.setInstanceFollowRedirects(true);//是成員函式,僅作用於當前函式,設定這個連線是否可以被重定向 urlConnection.setReadTimeout(3000);//響應的超時時間 urlConnection.setDoInput(true);//設定這個連線是否可以寫入資料 urlConnection.setDoOutput(true);//設定這個連線是否可以輸出資料 urlConnection.setRequestMethod("POST");//設定請求的方式 urlConnection.setRequestProperty("Content-Type", "application/json;charset=UTF-8");//設定訊息的型別 urlConnection.connect();// 連線,從上述至此的配置必須要在connect之前完成,實際上它只是建立了一個與伺服器的TCP連線 JSONObject json = new JSONObject();//建立json物件 json.put("name", URLEncoder.encode(name, "UTF-8"));//使用URLEncoder.encode對特殊和不可見字元進行編碼 json.put("password", URLEncoder.encode(password, "UTF-8"));//把資料put進json物件中 String jsonstr = json.toString();//把JSON物件按JSON的編碼格式轉換為字串 //-------------使用位元組流傳送資料-------------- //OutputStream out = urlConnection.getOutputStream(); //BufferedOutputStream bos = new BufferedOutputStream(out);//緩衝位元組流包裝位元組流 //byte[] bytes = jsonstr.getBytes("UTF-8");//把字串轉化為位元組陣列 //bos.write(bytes);//把這個位元組陣列的資料寫入緩衝區中 //bos.flush();//重新整理緩衝區,傳送資料 //out.close(); //bos.close(); //------------字元流寫入資料------------ OutputStream out = urlConnection.getOutputStream();//輸出流,用來發送請求,http請求實際上直到這個函式裡面才正式傳送出去 BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(out));//建立字元流物件並用高效緩衝流包裝它,便獲得最高的效率,傳送的是字串推薦用字元流,其它資料就用位元組流 bw.write(jsonstr);//把json字串寫入緩衝區中 bw.flush();//重新整理緩衝區,把資料傳送出去,這步很重要 out.close(); bw.close();//使用完關閉 if(urlConnection.getResponseCode()==HttpURLConnection.HTTP_OK){//得到服務端的返回碼是否連線成功 //------------位元組流讀取服務端返回的資料------------ //InputStream in = urlConnection.getInputStream();//用輸入流接收服務端返回的迴應資料 //BufferedInputStream bis = new BufferedInputStream(in);//高效緩衝流包裝它,這裡用的是位元組流來讀取資料的,當然也可以用字元流 //byte[] b = new byte[1024]; //int len = -1; //StringBuffer buffer = new StringBuffer();//用來接收資料的StringBuffer物件 //while((len=bis.read(b))!=-1){ //buffer.append(new String(b, 0, len));//把讀取到的位元組陣列轉化為字串 //} //in.close(); //bis.close(); //Log.d("zxy", buffer.toString());//{"json":true} //JSONObject rjson = new JSONObject(buffer.toString());//把返回來的json編碼格式的字串資料轉化成json物件 //------------字元流讀取服務端返回的資料------------ InputStream in = urlConnection.getInputStream(); BufferedReader br = new BufferedReader(new InputStreamReader(in)); String str = null; StringBuffer buffer = new StringBuffer(); while((str = br.readLine())!=null){//BufferedReader特有功能,一次讀取一行資料 buffer.append(str); } in.close(); br.close(); JSONObject rjson = new JSONObject(buffer.toString()); Log.d("zxy", "rjson="+rjson);//rjson={"json":true} boolean result = rjson.getBoolean("json");//從rjson物件中得到key值為"json"的資料,這裡服務端返回的是一個boolean型別的資料 if(result){//判斷結果是否正確 mHandler.sendEmptyMessage(USERLOGIN_SUCCESS); }else{ mHandler.sendEmptyMessage(USERLOGIN_FAILED); } }else{ mHandler.sendEmptyMessage(USERLOGIN_FAILED); } } catch (Exception e) { mHandler.sendEmptyMessage(USERLOGIN_FAILED); }finally{ urlConnection.disconnect();//使用完關閉TCP連線,釋放資源 } }
服務端的程式碼為:(使用HttpUrlConnection,服務端是用輸入流來讀取客戶端發過來的資料。而使用HttpClient的話,則服務端用相應的key值來獲取資料)
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding("UTF-8"); System.out.println(request.getContentType());//得到客戶端傳送過來內容的型別,application/json;charset=UTF-8 System.out.println(request.getRemoteAddr());//得到客戶端的ip地址,192.168.1.101 //------------使用位元組流讀取客戶端傳送過來的資料------------ // BufferedInputStream bis = new BufferedInputStream(request.getInputStream()); // byte[] b = new byte[1024]; // int len=-1; // StringBuffer buffer = new StringBuffer(); // while((len=bis.read(b))!=-1){ // buffer.append(new String(b, 0, len)); // } // bis.close(); // System.out.println("buffer="+buffer); // JSONObject json = JSONObject.fromObject(buffer.toString()); BufferedReader br = new BufferedReader(new InputStreamReader(//使用字元流讀取客戶端發過來的資料 request.getInputStream())); String line = null; StringBuffer s = new StringBuffer(); while ((line = br.readLine()) != null) { s.append(line); } br.close(); System.out.println(s.toString());//{"password":"123456","name":"admin"} JSONObject json = JSONObject.fromObject(s.toString());//轉化為jSONObject物件 String name = json.getString("name");//從json物件中得到相應key的值 String password = json.getString("password"); response.setCharacterEncoding("UTF-8"); response.setContentType("application/json;charset=UTF-8"); if (name.equals("admin") && password.equals("123456")) { JSONObject rjson = new JSONObject(); rjson.put("json", true);//返回boolean型別的值 System.out.println("rjson=" + rjson); // response.getWriter().write(rjson.toString());//向客戶端傳送一個帶有json物件內容的響應 response.getOutputStream().write(rjson.toString().getBytes("UTF-8"));//向客戶端傳送一個帶有json物件內容的響應 } else { JSONObject rjson = new JSONObject(); rjson.put("json", false); System.out.println("rjson=" + rjson); // response.getWriter().write(rjson.toString());//向客戶端傳送一個帶有json物件內容的響應 response.getOutputStream().write(rjson.toString().getBytes("UTF-8"));//向客戶端傳送一個帶有json物件內容的響應 } }
二、我們再來看看用Get請求:
public void httpUrlConnGet(String name,String password){
HttpURLConnection urlConnection = null;
URL url = null;
try {
String urlStr = "http://192.168.1.105:8080/KYDServer/servlet/Login?name="+name+"&password="+password;
url = new URL(urlStr);
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.connect();
if(urlConnection.getResponseCode()==HttpURLConnection.HTTP_OK){
InputStream in = urlConnection.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(in));
String line = null;
StringBuffer buffer = new StringBuffer();
while((line=br.readLine())!=null){
buffer.append(line);
}
in.close();
br.close();
String result = buffer.toString();
if(result.equals("ok")){
mHandler.sendEmptyMessage(USERLOGIN_SUCCESS);
}else{
mHandler.sendEmptyMessage(USERLOGIN_FAILED);
}
}else{
mHandler.sendEmptyMessage(CONN_FIALED);
}
} catch (Exception e) {
mHandler.sendEmptyMessage(CONN_FIALED);
}finally{
urlConnection.disconnect();
}
}
Get請求的服務端程式碼我就不寫啦,但是服務端是用key值來獲取資料的哦,這個和post的方式不同。
所以總結一下:
- 使用HttpUrlConnection請求伺服器的話:
用Get請求:客戶端的資料是放在url中的,通過url來傳給伺服器。服務端接收客戶端發來的資料是用對應的key值的,服務端返回資料給客戶端是用response.getWriter().write()或response.getOutputStream().write()來返回的,客戶端接收服務端返回來的資料是用urlConnection.getInputStream()輸入流來讀取的。
用Post請求:客戶端的資料是放在正文中的,即是通過urlConnection.getOutputStream()輸出流來發送給伺服器的。服務端接收客戶端發來的資料是用request.getInputStream()輸入流來讀取的,服務端返回資料給客戶端是用response.getWriter().write()或response.getOutputStream().write()來返回的,客戶端接收服務端返回來的資料是用urlConnection.getInputStream()輸入流來讀取的。【注】:使用HttpUrlConnection客戶端的傳送和接收資料都是用流操作的。
- 使用HttpClient請求伺服器的話:
用Get請求:客戶端的資料是放在url中的,通過url傳給伺服器。服務端接收客戶端發來的資料是用對應的key值的,服務端返回資料給客戶端是用response.getWriter().write()或response.getOutputStream().write()來返回的,客戶端接收服務端返回來的資料是用
response.getEntity()來接收。
用Post請求:客戶端的資料是放在List<NameValuePair>parameters集合中,通過post.setEntity(new UrlEncodedFormEntity(parameters, "UTF-8"))傳送給伺服器。服務端接收客戶端發來的資料是用對應的key值的,服務端返回資料給客戶端是用response.getWriter().write()或response.getOutputStream().write()來返回的,客戶端接收服務端返回來的資料是用
response.getEntity()來接收。
HttpURLConnection.connect()函式,實際上只是建立了一個與伺服器的tcp連線,並沒有實際傳送http請求。無論是post還是get,http請求實際上直到HttpURLConnection.getInputStream()這個函式裡面才正式傳送出去。
在HttpUrlConnection中,順序是重中之重,對urlConnection物件的一切配置(那一堆set函式)都必須要在connect()函式執行之前完成。
http請求實際上由兩部分組成,一個是http頭,所有關於此次http請求的配置都在http頭裡面定義,另一個是正文content。在connect()函式裡面,會根據HttpURLConnection物件的配置值生成http頭,因此在呼叫connect函式之前,就必須把所有的配置準備好。
緊接著http頭的是http請求的正文,正文的內容通過outputStream寫入,實際上outputStream不是一個網路流,充其量是個字串流,往裡面寫入的東西不會立即傳送到網路,而是在流關閉後,根據輸入的內容生成http正文。
轉載請註明出處!!!