使用Servlet返回JSON数据到客户端:
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());
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);
结果在意料之中,如下图所示:
使用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);
10
ServletActionContext.getRequest().setAttribute(
"data"
, jsonObject.toString());
因为是常规的Struts流程配置,所以配置内容就不再展示了。
JSP代码就非常简单了,
1
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
结果如图所示:
在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());
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() {
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"
>
6
<
param
name
=
"root"
>dataMap</
param
>
凡是使用Struts2序列化对象到JSON的action,所在的package必须继承自json-default,注意,这里唯一的result,没有指定name属性。
结果如下图所示:
上面很详细的说明了在WEB应用中如何返回JSON数据到客户端,讲了那么多种方式,涉及的技术核心无非只有两点:
1、将对象转换成符合JSON语法格式的字符串; 2、将符合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中配置的参数的含义及其常见常见配置吧:
04
<
param
name
=
"root"
>dataMap</
param
>
06
<
param
name
=
"excludeNullProperties"
>true</
param
>
08
<
param
name
=
"includeProperties"
>
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;
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
);
050
ServletActionContext.getRequest().setAttribute(
"data"
, jsonObject.toString());
055
* 测试通过action以Struts2默认方式返回JSON数据
058
public
String testByAction() {
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数据
075
* @throws IOException
077
public
void
doAction()
throws
IOException{
078
HttpServletResponse response=ServletActionContext.getResponse();
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());
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"
>
11
<
param
name
=
"root"
>dataMap</
param
>
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
>