JSON建構於兩種結構:html
「名稱/值」對的集合(A collection of name/value pairs)。不一樣的語言中,它被理解爲對象(object),紀錄(record),結構(struct),字典(dictionary),哈希表 (hash table),有鍵列表(keyed list),或者關聯數組 (associative array)。java
值的有序列表(An ordered list of values)。在大部分語言中,它被理解爲數組(array)。apache
由於JSON中的值(value)能夠是雙引號括起來的字符串(string)、數值(number)、true、false、 null、對象(object)或者數組(array),且這些結構能夠嵌套,這種特性給予JSON表達數據以無限的可能:它既能夠表達一個簡單的 key/value,也能夠表達一個複雜的Map或List,並且它是易於閱讀和理解的。json
Struts2中JSON的用武之地數組
由於JSON是脫離語言的理想的數據交換格式,因此它被頻繁的應用在客戶端與服務器的通訊過程當中,這一點是毋庸置疑的。而在客戶端與服務器的通訊過程 中,JSON數據的傳遞又被分爲服務器向客戶端傳送JSON數據,和客戶端向服務器傳送JSON數據,前者的核心過程當中將對象轉換成JSON,然後者的核 心是將JSON轉換成對象,這是本質的區別。另外,值得一提的是,JSON數據在傳遞過程當中,其實就是傳遞一個普通的符合JSON語法格式的字符串而已,所謂的「JSON對象」是指對這個JSON字符串解析和包裝後的結果,這一點請牢記,由於下面的內容會依賴這一點。瀏覽器
Struts2返回JSON數據到客戶端服務器
這是最多見的需求,在AJAX大行其道的今天,向服務器請求JSON數據已成爲每個WEB應用必備的功能。拋開Struts2暫且不提,在常規WEB應 用中由服務器返回JSON數據到客戶端有兩種方式:一是在Servlet中輸出JSON串,二是在JSP頁面中輸出JSON串。上文提到,服務器像客戶端 返回JSON數據,其實就是返回一個符合JSON語法規範的字符串,因此在上述兩種 方法中存在一個共同點,就是將須要返回的數據包裝稱符合JSON語法規範的字符串後在頁面中顯示。以下所示jsp
使用Servlet返回JSON數據到客戶端:post
01 |
package cn.ysh.studio.struts2.json.demo.servlet; |
03 |
import java.io.IOException; |
04 |
import java.io.PrintWriter; |
06 |
import javax.servlet.ServletException; |
07 |
import javax.servlet.http.HttpServlet; |
08 |
import javax.servlet.http.HttpServletRequest; |
09 |
import javax.servlet.http.HttpServletResponse; |
11 |
import net.sf.json.JSONObject; |
13 |
import cn.ysh.studio.struts2.json.demo.bean.User; |
15 |
public class JSON extends HttpServlet { |
20 |
private static final long serialVersionUID = 1L; |
23 |
* The doGet method of the servlet. <br> |
25 |
* This method is called when a form has its tag value method equals to get. |
27 |
* @param request the request send by the client to the server |
28 |
* @param response the response send by the server to the client |
29 |
* @throws ServletException if an error occurred |
30 |
* @throws IOException if an error occurred |
32 |
public void doGet(HttpServletRequest request, HttpServletResponse response) |
33 |
throws ServletException, IOException { |
35 |
response.setContentType( "text/html" ); |
36 |
PrintWriter out = response.getWriter(); |
40 |
user.setName( "JSONServlet" ); |
41 |
user.setPassword( "JSON" ); |
42 |
user.setSay( "Hello , i am a servlet !" ); |
43 |
JSONObject json= new JSONObject(); |
44 |
json.accumulate( "success" , true ); |
45 |
json.accumulate( "user" , user); |
46 |
out.println(json.toString()); |
47 |
// 由於JSON數據在傳遞過程當中是以普通字符串形式傳遞的,因此咱們也能夠手動拼接符合JSON語法規範的字符串輸出到客戶端 |
48 |
// 如下這兩句的做用與38-46行代碼的做用是同樣的,將向客戶端返回一個User對象,和一個success字段 |
49 |
// String jsonString="{\"user\":{\"id\":\"123\",\"name\":\"JSONServlet\",\"say\":\"Hello , i am a servlet !\",\"password\":\"JSON\"},\"success\":true}"; |
50 |
// out.println(jsonString); |
56 |
* The doPost method of the servlet. <br> |
58 |
* This method is called when a form has its tag value method equals to post. |
60 |
* @param request the request send by the client to the server |
61 |
* @param response the response send by the server to the client |
62 |
* @throws ServletException if an error occurred |
63 |
* @throws IOException if an error occurred |
65 |
public void doPost(HttpServletRequest request, HttpServletResponse response) |
66 |
throws ServletException, IOException { |
67 |
doGet(request, response); |
結果在乎料之中,以下圖所示:測試
![a1.jpg a1.jpg](http://static.javashuo.com/static/loading.gif)
使用JSP(或html等)返回JSON數據到客戶端:
1 |
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> |
2 |
{"user":{"id":"123","name":"JSONJSP","say":"Hello , i am a JSP !","password":"JSON"},"success":true} |
這個就不用去看結果了吧。
再回到Struts,在Struts的MVC模型中,Action替代Servlet擔當了Model的角色,因此對於Struts而言,返回 JSON數據到客戶端,跟傳統的WEB應用同樣,存在兩種方式,即在Action中輸出JSON數據,和在視圖資源中輸出JSON數據。再往下細分的話, 在Action中輸出JSON數據又分爲兩種方式,一是使用傳統方式輸出本身包裝後的JSON數據,二是使用Struts自帶的JSON數據封裝功能來自 動包裝並返回JSON數據。
在視圖資源中輸出JSON數據
Action處理完用戶請求後,將數據存放在某一位置,如request中,並返回視圖,而後Struts將跳轉至該視圖資源,在該視圖中,咱們須要作的 是將數據從存放位置中取出,而後將其轉換爲JSON字符串,輸出在視圖中。這跟傳統WEB應用中在JSP頁面輸出JSON數據的作法一模一樣:
01 |
public String testByJSP() { |
02 |
User user = new User(); |
04 |
user.setName( "Struts2" ); |
05 |
user.setPassword( "123" ); |
06 |
user.setSay( "Hello world !" ); |
07 |
JSONObject jsonObject= new JSONObject(); |
08 |
jsonObject.accumulate( "user" , user); |
09 |
//這裏在request對象中放了一個data,因此struts的result配置中不能有type="redirect" |
10 |
ServletActionContext.getRequest().setAttribute( "data" , jsonObject.toString()); |
由於是常規的Struts流程配置,因此配置內容就再也不展現了。
JSP代碼就很是簡單了,
1 |
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> |
結果如圖所示:
![a2.jpg a2.jpg](http://static.javashuo.com/static/loading.gif)
在Action中以傳統方式輸出JSON數據
這一點跟傳統的Servlet的處理方式基本上如出一轍,代碼以下
01 |
public void doAction() throws IOException{ |
02 |
HttpServletResponse response=ServletActionContext.getResponse(); |
04 |
response.setContentType( "text/html" ); |
06 |
out = response.getWriter(); |
10 |
user.setName( "JSONActionGeneral" ); |
11 |
user.setPassword( "JSON" ); |
12 |
user.setSay( "Hello , i am a action to print a json!" ); |
13 |
JSONObject json= new JSONObject(); |
14 |
json.accumulate( "success" , true ); |
15 |
json.accumulate( "user" , user); |
16 |
out.println(json.toString()); |
17 |
// 由於JSON數據在傳遞過程當中是以普通字符串形式傳遞的,因此咱們也能夠手動拼接符合JSON語法規範的字符串輸出到客戶端 |
18 |
// 如下這兩句的做用與38-46行代碼的做用是同樣的,將向客戶端返回一個User對象,和一個success字段 |
19 |
// String jsonString="{\"user\":{\"id\":\"123\",\"name\":\"JSONActionGeneral\",\"say\":\"Hello , i am a action to print a json!\",\"password\":\"JSON\"},\"success\":true}"; |
20 |
// out.println(jsonString); |
struts.xml中的配置:
1 |
< package name = "default" extends = "struts-default" namespace = "/" > |
2 |
< action name = "testJSONFromActionByGeneral" class = "cn.ysh.studio.struts2.json.demo.action.UserAction" method = "doAction" > |
注意:這個action沒有result,且doAction方法沒有返回值!
就再也不貼圖了,由於結果可想而知!
在Action中以Struts2的方式輸出JSON數據
本着「不重複發明輪子」的原則,咱們將轉換JSON數據的工做交給Struts2來作,那麼相對於在Action中以傳統方式輸出JSON不一樣 的是,Action是須要將注意力放在業務處理上,而無需關心處理結果是如何被轉換成JSON被返回客戶端的——這些 工做經過簡單的配置,Struts2會幫咱們作的更好。
01 |
public String testByAction() { |
02 |
// dataMap中的數據將會被Struts2轉換成JSON字符串,因此這裏要先清空其中的數據 |
04 |
User user = new User(); |
06 |
user.setName( "JSONActionStruts2" ); |
07 |
user.setPassword( "123" ); |
08 |
user.setSay( "Hello world !" ); |
09 |
dataMap.put( "user" , user); |
11 |
dataMap.put( "success" , true ); |
struts.xml中action的配置:
1 |
< package name = "json" extends = "json-default" namespace = "/test" > |
2 |
< action name = "testByAction" |
3 |
class = "cn.ysh.studio.struts2.json.demo.action.UserAction" method = "testByAction" > |
5 |
<!-- 這裏指定將被Struts2序列化的屬性,該屬性在action中必須有對應的getter方法 --> |
6 |
< param name = "root" >dataMap</ param > |
凡是使用Struts2序列化對象到JSON的action,所在的package必須繼承自json-default,注意,這裏惟一的result,沒有指定name屬性。
結果以下圖所示:
![a3.jpg a3.jpg](http://static.javashuo.com/static/loading.gif)
上面很詳細的說明了在WEB應用中如何返回JSON數據到客戶端,講了那麼多種方式,涉及的技術核心無非只有兩點:
一、將對象轉換成符合JSON語法格式的字符串;
二、將符合JSON語法格式的字符串返回客戶端;
第二點是整個實現過程的本質,但卻不難作到;第一點其實也不難,他甚至有兩種作法,一是經過字符串拼接方式,而是經過JSONObject以對象方式轉換。看下面的一個例子:
01 |
package cn.ysh.studio.struts2.json.demo.test; |
03 |
import cn.ysh.studio.struts2.json.demo.bean.User; |
04 |
import net.sf.json.JSONObject; |
06 |
public class JSONTest { |
12 |
public JSONObject bean2json() { |
13 |
User user = new User(); |
14 |
user.setId( "JSONTest" ); |
15 |
user.setName( "JSONTest" ); |
16 |
user.setPassword( "JSON" ); |
17 |
user.setSay( "Hello,i am JSONTest.java" ); |
18 |
JSONObject jsonObject = new JSONObject(); |
19 |
jsonObject.accumulate( "user" , user); |
20 |
System.out.println( "User轉換後的字符串:" +jsonObject.toString()); |
25 |
* 從JSONObject對象中反向解析出User對象 |
28 |
public void json2bean(JSONObject jsonObject) { |
29 |
User user=(User)JSONObject.toBean((JSONObject)jsonObject.get( "user" ),User. class ); |
30 |
System.out.println( "轉換獲得的User對象的Name爲:" +user.getName()); |
33 |
public static void main(String[] s) { |
34 |
JSONTest tester= new JSONTest(); |
35 |
tester.json2bean(tester.bean2json()); |
JSON格式的字符串返回到客戶端後,客戶端會將其解析並封裝成真正的JSON對象,以供JS調用。
總結上述,其實只要明白了服務器返回JSON數據到客戶端的原理,作起來就遊刃有餘了,他甚至有很是多的可選方案,但既然是基於 Struts2的實現,那麼確定仍是要用Struts2的方式來作啦,由於這樣確實能夠省不少事。另外,在文章的最後,說明一下返回JSON數據時在 result中配置的參數的含義及其常見常見配置吧:
02 |
<!-- 這裏指定將被Struts2序列化的屬性,該屬性在action中必須有對應的getter方法 --> |
03 |
<!-- 默認將會序列全部有返回值的getter方法的值,而不管該方法是否有對應屬性 --> |
04 |
< param name = "root" >dataMap</ param > |
06 |
< param name = "excludeNullProperties" >true</ param > |
07 |
<!-- 這裏指定將序列化dataMap中的那些屬性 --> |
08 |
< param name = "includeProperties" > |
11 |
<!-- 這裏指定將要從dataMap中排除那些屬性,這些排除的屬性將不被序列化,一半不與上邊的參數配置同時出現 --> |
12 |
< param name = "excludeProperties" > |
值得一提的是經過Struts2來返回JSON數據,在IE中會提示下載,這個不用關心,換個瀏覽器就能正常展現JSON數據,而在JS調用中,更是毫無影響。
下面是整個Action的完整代碼:
001 |
package cn.ysh.studio.struts2.json.demo.action; |
003 |
import java.io.IOException; |
004 |
import java.io.PrintWriter; |
005 |
import java.util.HashMap; |
006 |
import java.util.Map; |
008 |
import javax.servlet.http.HttpServletResponse; |
010 |
import org.apache.struts2.ServletActionContext; |
012 |
import net.sf.json.JSONObject; |
014 |
import cn.ysh.studio.struts2.json.demo.bean.User; |
016 |
import com.opensymphony.xwork2.ActionSupport; |
018 |
public class UserAction extends ActionSupport { |
023 |
private static final long serialVersionUID = 1L; |
025 |
//將會被Struts2序列化爲JSON字符串的對象 |
026 |
private Map<String, Object> dataMap; |
031 |
public UserAction() { |
033 |
dataMap = new HashMap<String, Object>(); |
037 |
* 測試經過action以視圖方式返回JSON數據 |
040 |
public String testByJSP() { |
041 |
User user = new User(); |
043 |
user.setName( "JSONActionJSP" ); |
044 |
user.setPassword( "123" ); |
045 |
user.setSay( "Hello world !" ); |
046 |
JSONObject jsonObject= new JSONObject(); |
047 |
jsonObject.accumulate( "user" , user); |
048 |
jsonObject.accumulate( "success" , true ); |
049 |
//這裏在request對象中放了一個data,因此struts的result配置中不能有type="redirect" |
050 |
ServletActionContext.getRequest().setAttribute( "data" , jsonObject.toString()); |
055 |
* 測試經過action以Struts2默認方式返回JSON數據 |
058 |
public String testByAction() { |
059 |
// dataMap中的數據將會被Struts2轉換成JSON字符串,因此這裏要先清空其中的數據 |
061 |
User user = new User(); |
063 |
user.setName( "JSONActionStruts2" ); |
064 |
user.setPassword( "123" ); |
065 |
user.setSay( "Hello world !" ); |
066 |
dataMap.put( "user" , user); |
068 |
dataMap.put( "success" , true ); |
074 |
* 經過action是以傳統方式返回JSON數據 |
077 |
public void doAction() throws IOException{ |
078 |
HttpServletResponse response=ServletActionContext.getResponse(); |
079 |
//如下代碼從JSON.java中拷過來的 |
080 |
response.setContentType( "text/html" ); |
082 |
out = response.getWriter(); |
084 |
User user= new User(); |
086 |
user.setName( "JSONActionGeneral" ); |
087 |
user.setPassword( "JSON" ); |
088 |
user.setSay( "Hello , i am a action to print a json!" ); |
089 |
JSONObject json= new JSONObject(); |
090 |
json.accumulate( "success" , true ); |
091 |
json.accumulate( "user" , user); |
092 |
out.println(json.toString()); |
093 |
// 由於JSON數據在傳遞過程當中是以普通字符串形式傳遞的,因此咱們也能夠手動拼接符合JSON語法規範的字符串輸出到客戶端 |
094 |
// 如下這兩句的做用與38-46行代碼的做用是同樣的,將向客戶端返回一個User對象,和一個success字段 |
095 |
// String jsonString="{\"user\":{\"id\":\"123\",\"name\":\"JSONActionGeneral\",\"say\":\"Hello , i am a action to print a json!\",\"password\":\"JSON\"},\"success\":true}"; |
096 |
// out.println(jsonString); |
102 |
* Struts2序列化指定屬性時,必須有該屬性的getter方法,實際上,若是沒有屬性,而只有getter方法也是能夠的 |
105 |
public Map<String, Object> getDataMap() { |
完整的struts.xml配置文件以下:
01 |
<? xml version = "1.0" encoding = "UTF-8" ?> |
02 |
<!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN" |
03 |
"http://struts.apache.org/dtds/struts-2.0.dtd"> |
05 |
< package name = "json" extends = "json-default" namespace = "/test" > |
06 |
< action name = "testByAction" |
07 |
class = "cn.ysh.studio.struts2.json.demo.action.UserAction" method = "testByAction" > |
09 |
<!-- 這裏指定將被Struts2序列化的屬性,該屬性在action中必須有對應的getter方法 --> |
10 |
<!-- 默認將會序列全部有返回值的getter方法的值,而不管該方法是否有對應屬性 --> |
11 |
< param name = "root" >dataMap</ param > |
14 |
<param name="excludeNullProperties">true</param> |
16 |
<!-- 這裏指定將序列化dataMap中的那些屬性 --> |
18 |
<param name="includeProperties"> |
22 |
<!-- 這裏指定將要從dataMap中排除那些屬性,這些排除的屬性將不被序列化,一半不與上邊的參數配置同時出現 --> |
24 |
<param name="excludeProperties"> |
31 |
< package name = "default" extends = "struts-default" namespace = "/" > |
32 |
< action name = "testJSONFromActionByGeneral" |
33 |
class = "cn.ysh.studio.struts2.json.demo.action.UserAction" method = "doAction" > |
35 |
< action name = "testByJSP" |
36 |
class = "cn.ysh.studio.struts2.json.demo.action.UserAction" method = "testByJSP" > |
37 |
< result name = "success" >/actionJSP.jsp</ result > |
轉載請註明出處: http://yshjava.iteye.com/blog/1333104