首页 > 代码库 > 【Android】与服务器实现JSON数据通信

【Android】与服务器实现JSON数据通信

一、前言

  作为一名移动端开发人员,具备一定的服务端开发能力也是非常必要的,本篇博客讲述如何在Android和服务器之间实现JSON数据通信交互,博客内容基于另外一篇博客:【Web】Eclipse + Maven + Struts搭建服务器。

 

二、服务器端改造

  在博客【Web】Eclipse + Maven + Struts搭建服务器中,我们实现了服务器的搭建,现在要做的事情就是让它返回的数据是一个JSON格式的,这样在获得请求的时候,我们才可以得到JSON数据,其配置改变如下。

  首先我们新建一个com.android.display.bean包,新建一个User类,如下:

 1 package conm.android.sdisplay.bean; 2  3 public class User { 4     String id; 5     String name; 6     String password; 7     String say; 8     public String getId() { 9         return id;10     }11     public void setId(String id) {12         this.id = id;13     }14     public String getName() {15         return name;16     }17     public void setName(String name) {18         this.name = name;19     }20     public String getPassword() {21         return password;22     }23     public void setPassword(String password) {24         this.password = password;25     }26     public String getSay() {27         return say;28     }29     public void setSay(String say) {30         this.say = say;31     }32 }
View Code

  修改HelloAction代码如下:

 1 package com.android.displaymain; 2  3 import java.util.HashMap; 4 import java.util.Map; 5  6 import com.opensymphony.xwork2.ActionSupport; 7  8 import conm.android.sdisplay.bean.User; 9 10 public class HelloAction extends ActionSupport{11     //将会被Struts2序列化为JSON字符串的对象12     private Map<String, Object> dataMap;13     14     @Override15     public String execute() throws Exception {16         // dataMap中的数据将会被Struts2转换成JSON字符串,所以这里要先清空其中的数据17         dataMap = new HashMap<String, Object>();18         User user = new User();19         user.setId("123");20         user.setName("Android");21         user.setPassword("abcdefg");22         user.setSay("Hello world !");23         dataMap.put("user", user);24         // 放入一个是否操作成功的标识25         dataMap.put("success", true);26         // 返回结果27         return SUCCESS;28     }29 30     public Map<String, Object> getDataMap() {31         return dataMap;32     }33 34     public void setDataMap(Map<String, Object> dataMap) {35         this.dataMap = dataMap;36     }37 }
View Code

  我们的目标是将dataMap以JSON格式返回。现在Action已经完成了,但是还需要配置一下,修改struts.xml文件如下:

 1 <?xml version="1.0" encoding="UTF-8" ?> 2 <!DOCTYPE struts PUBLIC 3     "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN" 4     "http://struts.apache.org/dtds/struts-2.3.dtd"> 5      6 <struts> 7 <package name="com.android.server" namespace="/" extends="json-default" > 8     <default-action-ref name="index"/> 9     10     <action name="index">  11        <result>/index.jsp</result>      <!-- index.htm为项目根目录的默认页面 -->  12     </action>13     14     <action name="HelloAction" class="com.android.displaymain.HelloAction" method="execute">15         <result type="json"> <!-- 这里指定将被Struts2序列化的属性,该属性在action中必须有对应的getter方法 -->16              <param name="root">dataMap</param>17         </result>18     </action>19 </package> 20 </struts>
View Code

  注意两处改动,一是package的extends属性,二是HelloAction的结果返回类型,已经变为json,并且我们声明了一个叫做root的param,其值就是我们要JSON化的属性,至于为什么要声明,待会儿可以测试一下。

  修改完之后,我们因为使用JSON,需要Struts做一定的工作,我们就需要引入新的jar包,将pom文件改为:

 1 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 2   xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> 3   <modelVersion>4.0.0</modelVersion> 4   <groupId>com.android.network</groupId> 5   <artifactId>network_server</artifactId> 6   <packaging>war</packaging> 7   <version>0.0.1-SNAPSHOT</version> 8   <name>network_server Maven Webapp</name> 9   <url>http://maven.apache.org</url>10   <dependencies>11     <dependency>12       <groupId>junit</groupId>13       <artifactId>junit</artifactId>14       <version>3.8.1</version>15       <scope>test</scope>16     </dependency>17     <dependency>18             <groupId>org.apache.struts</groupId>19             <artifactId>struts2-core</artifactId>20             <version>2.3.16</version>21         </dependency>22         <dependency>23             <groupId>org.apache.commons</groupId>24             <artifactId>commons-io</artifactId>25             <version>1.3.2</version>26         </dependency>27         <dependency>28             <groupId>org.apache.struts</groupId>29             <artifactId>struts2-json-plugin</artifactId>30             <version>2.3.4</version>31         </dependency>32         <dependency>33             <groupId>commons-lang</groupId>34             <artifactId>commons-lang</artifactId>35             <version>2.3</version>36         </dependency>37   </dependencies>38   <build>39     <finalName>network_server</finalName>40   </build>41 </project>
View Code

  这里增添了两个jar包,最重要的一个是struts2-json-plugin。

  配置完成,我们再运行一下工程,运行起来以后,我们在浏览器(注:非IE,否则会要求你下载文件)中输入网址:http://localhost:8080/display/HelloAction就可以看到浏览器返回的数据:

{"success":true,"user":{"id":"123","name":"Android","password":"abcdefg","say":"Hello world !"}}

  很明显,服务器端已经正确返回我们需要的JSON数据了!读者可以去掉struts.xml配置中的关于root的配置,看看结果就明白这段配置的含义了。接下来就看Android端的了。

 

三、Android客户端构建

  Android实现的目标是:向服务器发送请求,并且携带参数,展示返回的JSON数据。Android环境的搭建就不赘述啦~直接进入正题。

  发起请求的Activity如下:

 1 package com.example.androidjson; 2  3 import java.io.IOException; 4  5 import org.apache.http.HttpResponse; 6 import org.apache.http.HttpStatus; 7 import org.apache.http.client.ClientProtocolException; 8 import org.apache.http.client.HttpClient; 9 import org.apache.http.client.methods.HttpPost;10 import org.apache.http.impl.client.DefaultHttpClient;11 import org.apache.http.util.EntityUtils;12 13 import android.app.Activity;14 import android.os.Bundle;15 import android.os.Handler;16 import android.os.Message;17 import android.view.View;18 import android.view.View.OnClickListener;19 import android.widget.Button;20 import android.widget.TextView;21 22 public class MainActivity extends Activity {23     TextView textView;24     Button dataButton;25     Handler mainHandler;26     27     @Override28     protected void onCreate(Bundle savedInstanceState) {29         super.onCreate(savedInstanceState);30         setContentView(R.layout.activity_main);31         32         textView = (TextView)findViewById(R.id.textView);33         dataButton = (Button)findViewById(R.id.dataButton);34         35         mainHandler = new Handler(){36 37             @Override38             public void handleMessage(Message msg) {39                 // TODO Auto-generated method stub40                 textView.setText(msg.obj.toString());41             }42         };43         44         dataButton.setOnClickListener(new OnClickListener(){45             @Override46             public void onClick(View v) {47                 // TODO Auto-generated method stub48                 Thread thread = new Thread(){49                     @Override50                     public void run() {51                         // TODO Auto-generated method stub52                         sendData();53                     }54                 };55                 56                 thread.start();57             }58         });59     }60     61     private void sendData(){62         HttpClient httpClient = new DefaultHttpClient();63         HttpPost httpPost = new HttpPost("http://192.168.0.102:8080/display/HelloAction");64         try {65             HttpResponse httpResponse = httpClient.execute(httpPost);66             if (httpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK) { 67                   // 取得返回的数据 68                   Message msg = mainHandler.obtainMessage(0, EntityUtils.toString(httpResponse.getEntity()));69                   mainHandler.sendMessage(msg);70             } 71         } catch (ClientProtocolException e) {72             // TODO Auto-generated catch block73             e.printStackTrace();74         } catch (IOException e) {75             // TODO Auto-generated catch block76             e.printStackTrace();77         } 78     }79 }
View Code

  按下按钮后返回结果如下:

到这里,基本功能已经完成,我们可以发起请求,获取到正确的JSON格式数据了。接下来就是解析JSON数据格式了~

  修改一下服务器端的HelloAction代码如下:

 1 package com.android.displaymain; 2  3 import java.util.HashMap; 4 import java.util.Map; 5  6 import com.opensymphony.xwork2.ActionSupport; 7  8 import conm.android.sdisplay.bean.User; 9 10 public class HelloAction extends ActionSupport{11     //将会被Struts2序列化为JSON字符串的对象12     private Map<String, Object> dataMap;13     14     private String name;15     16     @Override17     public String execute() throws Exception {18         // dataMap中的数据将会被Struts2转换成JSON字符串,所以这里要先清空其中的数据19         dataMap = new HashMap<String, Object>();20         User user = new User();21         user.setId("123");22         user.setName(name);23         user.setPassword("abcdefg");24         user.setSay("Hello world !");25         dataMap.put("user", user);26         // 放入一个是否操作成功的标识27         dataMap.put("success", true);28         // 返回结果29         return SUCCESS;30     }31 32     public Map<String, Object> getDataMap() {33         return dataMap;34     }35 36     public void setDataMap(Map<String, Object> dataMap) {37         this.dataMap = dataMap;38     }39 40     public String getName() {41         return name;42     }43 44     public void setName(String name) {45         this.name = name;46     }47 }
View Code

  这里要求我们传入一个参数name,并且设置到返回值中去。现在,我们的目标是通过JSON向服务器端发送带参数请求,并正确解析返回的数据。修改Activity代码如下:

  1 package com.example.androidjson;  2   3 import java.io.IOException;  4 import java.util.ArrayList;  5   6 import org.apache.http.HttpEntity;  7 import org.apache.http.HttpResponse;  8 import org.apache.http.HttpStatus;  9 import org.apache.http.NameValuePair; 10 import org.apache.http.client.ClientProtocolException; 11 import org.apache.http.client.HttpClient; 12 import org.apache.http.client.entity.UrlEncodedFormEntity; 13 import org.apache.http.client.methods.HttpPost; 14 import org.apache.http.impl.client.DefaultHttpClient; 15 import org.apache.http.message.BasicNameValuePair; 16 import org.apache.http.protocol.HTTP; 17 import org.apache.http.util.EntityUtils; 18 import org.json.JSONException; 19 import org.json.JSONObject; 20  21 import android.app.Activity; 22 import android.os.Bundle; 23 import android.os.Handler; 24 import android.os.Message; 25 import android.view.View; 26 import android.view.View.OnClickListener; 27 import android.widget.Button; 28 import android.widget.TextView; 29  30 public class MainActivity extends Activity { 31     TextView textView; 32     Button dataButton; 33     Handler mainHandler; 34      35     @Override 36     protected void onCreate(Bundle savedInstanceState) { 37         super.onCreate(savedInstanceState); 38         setContentView(R.layout.activity_main); 39          40         textView = (TextView)findViewById(R.id.textView); 41         dataButton = (Button)findViewById(R.id.dataButton); 42          43         mainHandler = new Handler(){ 44  45             @Override 46             public void handleMessage(Message msg) { 47                 // TODO Auto-generated method stub 48                 parseJSON(msg.obj.toString()); 49             } 50         }; 51          52         dataButton.setOnClickListener(new OnClickListener(){ 53             @Override 54             public void onClick(View v) { 55                 // TODO Auto-generated method stub 56                 Thread thread = new Thread(){ 57                     @Override 58                     public void run() { 59                         // TODO Auto-generated method stub 60                         sendData(); 61                     } 62                 }; 63                  64                 thread.start(); 65             } 66         }); 67     } 68      69     private void parseJSON(String result){ 70         JSONObject jsonObj; 71         try { 72             jsonObj = new JSONObject(result); 73             boolean resResult = jsonObj.getBoolean("success"); 74             JSONObject userObj = jsonObj.getJSONObject("user"); 75             String id = userObj.getString("id");  76             String name = userObj.getString("name");  77             String say = userObj.getString("say");  78             textView.setText("ID: "+ id + "\n姓名: " + name + "\n性别: " + say); 79         } catch (JSONException e) { 80             // TODO Auto-generated catch block 81             e.printStackTrace(); 82         } 83     } 84      85     private void sendData(){ 86         HttpClient httpClient = new DefaultHttpClient(); 87         HttpPost httpPost = new HttpPost("http://192.168.0.102:8080/display/HelloAction"); 88         try { 89             ArrayList<NameValuePair> list = new ArrayList<NameValuePair>();  90             list.add(new BasicNameValuePair("name", "大脚印"));  91             HttpEntity en = new UrlEncodedFormEntity(list, HTTP.UTF_8);  92             httpPost.setEntity(en);  93             HttpResponse httpResponse = httpClient.execute(httpPost); 94             if (httpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {  95                   // 取得返回的数据  96                   Message msg = mainHandler.obtainMessage(0, EntityUtils.toString(httpResponse.getEntity())); 97                   mainHandler.sendMessage(msg); 98             }  99         } catch (ClientProtocolException e) {100             // TODO Auto-generated catch block101             e.printStackTrace();102         } catch (IOException e) {103             // TODO Auto-generated catch block104             e.printStackTrace();105         } 106     }107 }
View Code

  点击Send Data 按钮:

至此,我们已经可以完成从数据库返回JSON格式的数据,并且正确解析数据~

 

五、总结

  突发奇想,想要自己走一遍Android客户端到服务器之间的数据传递流程,所以花了点时间研究了一下~

  使用JSON传递数据非常简单,尤其是当服务器使用Struts2时可以使用插件支持该功能,更是非常方便~

 

客户端 & 服务器端示例代码下载