• 【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     @Override
    15     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     @Override
    28     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             @Override
    38             public void handleMessage(Message msg) {
    39                 // TODO Auto-generated method stub
    40                 textView.setText(msg.obj.toString());
    41             }
    42         };
    43         
    44         dataButton.setOnClickListener(new OnClickListener(){
    45             @Override
    46             public void onClick(View v) {
    47                 // TODO Auto-generated method stub
    48                 Thread thread = new Thread(){
    49                     @Override
    50                     public void run() {
    51                         // TODO Auto-generated method stub
    52                         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 block
    73             e.printStackTrace();
    74         } catch (IOException e) {
    75             // TODO Auto-generated catch block
    76             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     @Override
    17     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 + "
    姓名: " + name + "
    性别: " + 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 block
    101             e.printStackTrace();
    102         } catch (IOException e) {
    103             // TODO Auto-generated catch block
    104             e.printStackTrace();
    105         } 
    106     }
    107 }
    View Code

      点击Send Data 按钮:

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

    五、总结

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

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

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

  • 相关阅读:
    记一次struts项目空指针异常
    struts2问题(已解决)java.nio.file.InvalidPathException: Illegal char <:> at index 3: jar:file:
    Road Map
    API
    Report of program history
    正则表达式验证用户信息
    RegExp( replace()的示例 )
    DOM与BOM部分示例
    伪类与伪元素
    第三次随笔(按钮外观改变)
  • 原文地址:https://www.cnblogs.com/lqminn/p/3788097.html
Copyright © 2020-2023  润新知