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实现。

posted @ 2016-12-20 22:04  尤克里里  阅读(6044)  评论(0编辑  收藏  举报