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

时间:2022-08-26 14:57:32

一、前言

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

二、服务器端改造

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

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

 package conm.android.sdisplay.bean;

 public class User {
String id;
String name;
String password;
String say;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getSay() {
return say;
}
public void setSay(String say) {
this.say = say;
}
}

  修改HelloAction代码如下:

 package com.android.displaymain;

 import java.util.HashMap;
import java.util.Map; import com.opensymphony.xwork2.ActionSupport; import conm.android.sdisplay.bean.User; public class HelloAction extends ActionSupport{
//将会被Struts2序列化为JSON字符串的对象
private Map<String, Object> dataMap; @Override
public String execute() throws Exception {
// dataMap中的数据将会被Struts2转换成JSON字符串,所以这里要先清空其中的数据
dataMap = new HashMap<String, Object>();
User user = new User();
user.setId("123");
user.setName("Android");
user.setPassword("abcdefg");
user.setSay("Hello world !");
dataMap.put("user", user);
// 放入一个是否操作成功的标识
dataMap.put("success", true);
// 返回结果
return SUCCESS;
} public Map<String, Object> getDataMap() {
return dataMap;
} public void setDataMap(Map<String, Object> dataMap) {
this.dataMap = dataMap;
}
}

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

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

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

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

 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.android.network</groupId>
<artifactId>network_server</artifactId>
<packaging>war</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>network_server Maven Webapp</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-core</artifactId>
<version>2.3.16</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-io</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-json-plugin</artifactId>
<version>2.3.4</version>
</dependency>
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.3</version>
</dependency>
</dependencies>
<build>
<finalName>network_server</finalName>
</build>
</project>

  这里增添了两个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如下:

 package com.example.androidjson;

 import java.io.IOException;

 import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils; import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView; public class MainActivity extends Activity {
TextView textView;
Button dataButton;
Handler mainHandler; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); textView = (TextView)findViewById(R.id.textView);
dataButton = (Button)findViewById(R.id.dataButton); mainHandler = new Handler(){ @Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
textView.setText(msg.obj.toString());
}
}; dataButton.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
Thread thread = new Thread(){
@Override
public void run() {
// TODO Auto-generated method stub
sendData();
}
}; thread.start();
}
});
} private void sendData(){
HttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost("http://192.168.0.102:8080/display/HelloAction");
try {
HttpResponse httpResponse = httpClient.execute(httpPost);
if (httpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
// 取得返回的数据
Message msg = mainHandler.obtainMessage(0, EntityUtils.toString(httpResponse.getEntity()));
mainHandler.sendMessage(msg);
}
} catch (ClientProtocolException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

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

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

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

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

 package com.android.displaymain;

 import java.util.HashMap;
import java.util.Map; import com.opensymphony.xwork2.ActionSupport; import conm.android.sdisplay.bean.User; public class HelloAction extends ActionSupport{
//将会被Struts2序列化为JSON字符串的对象
private Map<String, Object> dataMap; private String name; @Override
public String execute() throws Exception {
// dataMap中的数据将会被Struts2转换成JSON字符串,所以这里要先清空其中的数据
dataMap = new HashMap<String, Object>();
User user = new User();
user.setId("123");
user.setName(name);
user.setPassword("abcdefg");
user.setSay("Hello world !");
dataMap.put("user", user);
// 放入一个是否操作成功的标识
dataMap.put("success", true);
// 返回结果
return SUCCESS;
} public Map<String, Object> getDataMap() {
return dataMap;
} public void setDataMap(Map<String, Object> dataMap) {
this.dataMap = dataMap;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
}
}

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

 package com.example.androidjson;

 import java.io.IOException;
import java.util.ArrayList; import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;
import org.json.JSONException;
import org.json.JSONObject; import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView; public class MainActivity extends Activity {
TextView textView;
Button dataButton;
Handler mainHandler; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); textView = (TextView)findViewById(R.id.textView);
dataButton = (Button)findViewById(R.id.dataButton); mainHandler = new Handler(){ @Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
parseJSON(msg.obj.toString());
}
}; dataButton.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
Thread thread = new Thread(){
@Override
public void run() {
// TODO Auto-generated method stub
sendData();
}
}; thread.start();
}
});
} private void parseJSON(String result){
JSONObject jsonObj;
try {
jsonObj = new JSONObject(result);
boolean resResult = jsonObj.getBoolean("success");
JSONObject userObj = jsonObj.getJSONObject("user");
String id = userObj.getString("id");
String name = userObj.getString("name");
String say = userObj.getString("say");
textView.setText("ID: "+ id + "\n姓名: " + name + "\n性别: " + say);
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} private void sendData(){
HttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost("http://192.168.0.102:8080/display/HelloAction");
try {
ArrayList<NameValuePair> list = new ArrayList<NameValuePair>();
list.add(new BasicNameValuePair("name", "大脚印"));
HttpEntity en = new UrlEncodedFormEntity(list, HTTP.UTF_8);
httpPost.setEntity(en);
HttpResponse httpResponse = httpClient.execute(httpPost);
if (httpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
// 取得返回的数据
Message msg = mainHandler.obtainMessage(0, EntityUtils.toString(httpResponse.getEntity()));
mainHandler.sendMessage(msg);
}
} catch (ClientProtocolException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

  点击Send Data 按钮:

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

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

五、总结

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

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

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