Android使用HttpURLConnection通過POST方式發送java序列化對象,netty發送序列化對象
使用HttpURLConnection類不僅可以向WebService發送字串,還可以發送序列化的java對象,實現Android手機和伺服器之間的資料互動。
Android端代碼:
1 public String SendDataByPost(String urlStr){ 2 URL url = null; 3 String result="";//要返回的結果 4 try { 5 url=new URL(urlStr); 6 HttpURLConnection httpURLConnection= (HttpURLConnection) url.openConnection(); 7 8 httpURLConnection.setConnectTimeout(2000);//設定連線逾時時間,單位ms 9 httpURLConnection.setReadTimeout(2000);//設定讀取逾時時間,單位ms10 11 //設定是否向httpURLConnection輸出,因為post請求參數要放在http本文內,所以要設定為true12 httpURLConnection.setDoOutput(true);13 14 //設定是否從httpURLConnection讀入,預設是false15 httpURLConnection.setDoInput(true);16 17 //POST請求不能用緩衝,設定為false18 httpURLConnection.setUseCaches(false);19 20 //傳送的內容是可序列化的21 //如果不設定此項,傳送序列化對象時,當WEB服務預設的不是這種類型時,會拋出java.io.EOFException錯誤22 httpURLConnection.setRequestProperty("Content-type","application/x-java-serialized-object");23 24 //佈建要求方法是POST25 httpURLConnection.setRequestMethod("POST");26 27 //串連伺服器28 httpURLConnection.connect();29 30 //getOutputStream會隱含調用connect(),所以不用寫上述的httpURLConnection.connect()也行。31 //得到httpURLConnection的輸出資料流32 OutputStream os= httpURLConnection.getOutputStream();33 34 //構建輸出資料流對象,以實現輸出序列化的對象35 ObjectOutputStream objOut=new ObjectOutputStream(os);36 37 //dataPost類是自訂的資料互動對象,只有兩個成員變數38 dataPost data= new dataPost("Tom",null);39 40 //向對象輸出資料流寫出資料,這些資料將存到記憶體緩衝區中41 objOut.writeObject(data);42 43 //重新整理對象輸出資料流,將位元組全部寫入輸出資料流中44 objOut.flush();45 46 //關閉流對象47 objOut.close();48 os.close();49 50 //將記憶體緩衝區中封裝好的完整的HTTP請求電文發送到服務端,並擷取訪問狀態51 if(HttpURLConnection.HTTP_OK==httpURLConnection.getResponseCode()){52 53 //得到httpURLConnection的輸入資料流,這裡麵包含伺服器返回來的java對象54 InputStream in=httpURLConnection.getInputStream();55 56 //構建對象輸入資料流,使用readObject()方法取出輸入資料流中的java對象57 ObjectInputStream inObj=new ObjectInputStream(in);58 data= (dataPost) inObj.readObject();59 60 //取出對象裡面的資料61 result=data.password;62 63 //輸出日誌,在控制台可以看到接收到的資料64 Log.w("HTTP",result+" :by post");65 66 //關閉建立的流67 in.close();68 inObj.close();69 }else{70 Log.w("HTTP","Connction failed"+httpURLConnection.getResponseCode());71 }72 } catch (Exception e) {73 e.printStackTrace();74 }75 return result;76 }
1 package com.example.com.example.data; 2 3 import java.io.Serializable; 4 5 //實現Serializable介面,使dataPost可序列化。 6 public class dataPost implements Serializable { 7 8 /*指定序列化版本號碼,保證序列化版本的一致性。在伺服器端,JVM會把傳來的位元組流的 9 serialVersionUID與本地相應實體(類)的serialVersionUID進行比較,如果相同就認10 為是一致的,可以進行還原序列化,否則就會出現序列化版本不一致的異常。*/11 private static final long serialVersionUID = 1L;12 13 String name;14 String password;15 public dataPost(String name, String password) {16 this.name = name;17 this.password = password;18 }19 20 public String getName() {21 return name;22 }23 24 public void setName(String name) {25 this.name = name;26 }27 28 public String getPassword() {29 return password;30 }31 32 public void setPassword(String password) {33 this.password = password;34 }35 36 }
服務端程式:
1 protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 2 3 ServletInputStream in=request.getInputStream(); 4 dataPost datap = null; 5 ObjectInputStream obj=new ObjectInputStream(in); 6 try { 7 datap= (dataPost) obj.readObject(); 8 } catch (ClassNotFoundException e) { 9 e.printStackTrace();10 }finally{11 obj.close();12 13 } 14 response.setContentType("application/x-java-serialized-object");15 OutputStream out=response.getOutputStream();16 ObjectOutputStream outObj=new ObjectOutputStream(out);17 datap.setPassword("9964646");18 outObj.writeObject(datap);19 outObj.flush();20 outObj.close();21 }
注意事項:1、用戶端url如果有中文會出現亂碼,需要對url進行編碼。
例如:
1 String url="你好";2 URI uri=new URI(url,false,"utf-8");3 url=uri.toString();
2、在Android主程式中調用SendDataByPost()方法時,要重新開一個線程,否則會阻塞主線程。
1 new Thread(new Runnable() { 2 @Override 3 public void run() { 4 HTTPURLConnectionGETData getData = new HTTPURLConnectionGETData(); 5 String result=getData.SendStringDataByPost(serverIP1); 6 if("".equals(result)){ 7 }else{ 8 Log.i("HTTP",result); 9 }10 }11 }).start();
3、Android端dataPost類的包名和server端dataPost的包名必須一致,否則就會出現找不到該類的異常。
java.lang.ClassNotFoundException: com.example.com.example.data.dataPost
at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1333)
4、Android端dataPost類的包名和server端dataPost的序列化版本必須一致,否則會報出serialVersionUID不同的錯誤。
Servlet.service() for servlet [com.test.stream.testStream] in context with path [/campus2] threw exception
java.io.InvalidClassException: com.example.com.example.data.dataPost; local class incompatible:
stream classdesc serialVersionUID = -1197271749879367300, local class serialVersionUID = -3085829960977977003
解決方案:
在兩端的dataPost類中顯式的指定序列化版本號碼,一般通過添加private static final long serialVersionUID = 1L實現。