1、前言html
做爲一名移動端開發人員,具有必定的服務端開發能力也是很是必要的,本篇博客講述如何在Android和服務器之間實現JSON數據通訊交互,博客內容基於另一篇博客:【Web】Eclipse + Maven + Struts搭建服務器。java
2、服務器端改造android
在博客【Web】Eclipse + Maven + Struts搭建服務器中,咱們實現了服務器的搭建,如今要作的事情就是讓它返回的數據是一個JSON格式的,這樣在得到請求的時候,咱們才能夠獲得JSON數據,其配置改變以下。數據庫
首先咱們新建一個com.android.display.bean包,新建一個User類,以下:apache
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 }
修改HelloAction代碼以下:json
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 }
咱們的目標是將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>
注意兩處改動,一是package的extends屬性,二是HelloAction的結果返回類型,已經變爲json,而且咱們聲明瞭一個叫作root的param,其值就是咱們要JSON化的屬性,至於爲何要聲明,待會兒能夠測試一下。服務器
修改完以後,咱們由於使用JSON,須要Struts作必定的工做,咱們就須要引入新的jar包,將pom文件改成:app
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>
這裏增添了兩個jar包,最重要的一個是struts2-json-plugin。jsp
配置完成,咱們再運行一下工程,運行起來之後,咱們在瀏覽器(注:非IE,不然會要求你下載文件)中輸入網址:http://localhost:8080/display/HelloAction就能夠看到瀏覽器返回的數據:
{"success":true,"user":{"id":"123","name":"Android","password":"abcdefg","say":"Hello world !"}}
很明顯,服務器端已經正確返回咱們須要的JSON數據了!讀者能夠去掉struts.xml配置中的關於root的配置,看看結果就明白這段配置的含義了。接下來就看Android端的了。
3、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 }
按下按鈕後返回結果以下:
到這裏,基本功能已經完成,咱們能夠發起請求,獲取到正確的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 }
這裏要求咱們傳入一個參數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 block 101 e.printStackTrace(); 102 } catch (IOException e) { 103 // TODO Auto-generated catch block 104 e.printStackTrace(); 105 } 106 } 107 }
點擊Send Data 按鈕:
至此,咱們已經能夠完成從數據庫返回JSON格式的數據,而且正確解析數據~
5、總結
突發奇想,想要本身走一遍Android客戶端到服務器之間的數據傳遞流程,因此花了點時間研究了一下~
使用JSON傳遞數據很是簡單,尤爲是當服務器使用Struts2時可使用插件支持該功能,更是很是方便~