Android使用HttpURLConnection通过POST方式发送java序列化对象
使用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);//设置读取超时时间,单位ms 10 11 //设置是否向httpURLConnection输出,因为post请求参数要放在http正文内,所以要设置为true 12 httpURLConnection.setDoOutput(true); 13 14 //设置是否从httpURLConnection读入,默认是false 15 httpURLConnection.setDoInput(true); 16 17 //POST请求不能用缓存,设置为false 18 httpURLConnection.setUseCaches(false); 19 20 //传送的内容是可序列化的 21 //如果不设置此项,传送序列化对象时,当WEB服务默认的不是这种类型时,会抛出java.io.EOFException错误 22 httpURLConnection.setRequestProperty("Content-type","application/x-java-serialized-object"); 23 24 //设置请求方法是POST 25 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实现。