最近,在使用Struts2+Jquery实现异步提交传递复杂JSON对象时候,遇到了各种问题,经过各方的不懈努力,最终找到了解决方案,记录下以备忘。
基础知识
JSON建构于两种结构:
1. “名称/值”对的集合(A collection of name/value pairs)。不同的语言中,它被理解为对象(object),记录(record),结构(struct),字典(dictionary),哈希表(hash table),有键列表(keyed list),或者关联数组 (associative array)。即为名称/值对。典型例子如:
{ "firstName": "Brett" }
2. 值的有序列表(An ordered list of values)。在大部分语言中,它被理解为数组(array),即本文所说的复杂JSON对象。典型例子如:
{
"urlsList": [
{
"id": "1",
"sort": "1"
},
{
"id": "12",
"sort": "2"
},
{
"id": "14",
"sort": "3"
},
{
"id": "13",
"sort": "4"
},
{
"id": "15",
"sort": "5"
},
{
"id": "16",
"sort": "6"
},
{
"id": "17",
"sort": "7"
}
]
}
1、前台JS代码
需要引入JS包
<
script type="text/javascript" src="images/json2/json2.min.js"
></
script
>
和
<
script type="text/javascript" src="images/jquery/jquery-1.6.3.min.js"
></
script
>
注:
<script type="text/javascript">
function save(){
//{"urlsList":[{"id":"1","sort":"1"},{"id":"12","sort":"2"},{"id":"14","sort":"3"},{"id":"13","sort":"4"},{"id":"15","sort":"5"},{"id":"16","sort":"6"},{"id":"17","sort":"7"}]};
var dataJSON=getDataJSON();//获得JSON对象
$.ajax({
type: "post",
url: "json/urlsJsonAciton_saveUrlsList",
contentType: "application/json;charset=utf-8",//不可缺少,代表使用JSON解析
data:JSON.stringify(dataJSON),//使用JSON.stringify(json)函数,将JSON对象转化为JSON字符串,进行传递
dataType:"json",//返回对象为JSON对象
success: function(msg){
alert( msg.data );
}
});
}
</script>
注:
<1>JSON异步提交,需要添加contentType;如果返回结果为JSON时候则应添加dataType属性。
<2>传递参数,为JSON对象时候,需要转换为JSON字符串,这里用的是JSON.stringify函数。
部分IE版本,会报“JSON未定义”的脚本错误,那是因为部分IE版本不支持
JSON
.
stringify
函数导致,导入json2.js(即
<
script type="text/javascript" src="images/json2/json2.min.js"
>
)即可解决问题。
2、struts.xml配置文件
根据jsonplugin官方的文档,页面传入的请求的content-type要是application/json,否则json的interceptor不会帮你将json转换为java对象,但是,jsonplugin中只是定义了json的interceptor,并没有将其放入到package的拦截器栈中,还需要我们自己放入自己的package中。
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.1//EN" "http://struts.apache.org/dtds/struts-2.1.dtd">
<struts>
<!-- struts设置JSON拦截器,能够将JSON对象转换为Java对象 -->
<package name="abstract_json" abstract="true" extends="json-default" namespace="/">
<interceptors>
<interceptor-stack name="myStack">
<interceptor-ref name="json"></interceptor-ref>
<interceptor-ref name="defaultStack" />
</interceptor-stack>
</interceptors>
<default-interceptor-ref name="myStack" />
</package>
<!-- 设置JSON处理的Action,需要继承自定义的abstract_json包 -->
<package name = "json" extends = "abstract_json" namespace="/json" >
<action name="urlsJsonAciton_*" class="com.haiwi.action.UrlsJsonAction" method="{1}">
<result type="json" ></result>
</action>
</package>
</struts>
注:部分程序出现使用GET方式能提交而POST不能提交的问题,则是由于stuts.xml中未设置JSON拦截器的原因。
3、Action
需要引入jar如下
首先需要定义一个转换JSON的Java对象
package com.haiwi.vo;
import java.util.List;
import com.haiwi.bean.UrlsBean;
public class UrlsVO {
private int id;
private String icon;
private String title;
private String url;
private int usedCount;
private String remark;
private List<UrlsBean> urlsBeanList;
private int sort;
private String msg;
private String location;//用于跳转新页面
public String getLocation() {
return location;
}
public void setLocation(String location) {
this.location = location;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public int getSort() {
return sort;
}
public void setSort(int sort) {
this.sort = sort;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getIcon() {
return icon;
}
public void setIcon(String icon) {
this.icon = icon;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public int getUsedCount() {
return usedCount;
}
public void setUsedCount(int usedCount) {
this.usedCount = usedCount;
}
public String getRemark() {
return remark;
}
public void setRemark(String remark) {
this.remark = remark;
}
public List<UrlsBean> getUrlsBeanList() {
return urlsBeanList;
}
public void setUrlsBeanList(List<UrlsBean> urlsBeanList) {
this.urlsBeanList = urlsBeanList;
}
}
然后定义一个Action类
当浏览器请求http://localhost:8080/Haiwi
/
json/urlsJsonAciton_saveUrlsList时候,struts2框架会查找对应的Java对象“urlsList”,并使用get和set方法解析注入数据。
小建议:Action中处理JSON可以考虑使用阿里巴巴的fastjson.jar
package com.haiwi.action;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;
import javax.servlet.http.HttpServletResponse;
import net.sf.json.JSONObject;
import org.apache.struts2.ServletActionContext;
import com.haiwi.vo.UrlsVO;
import com.opensymphony.xwork2.ActionSupport;
public class UrlsJsonAction extends ActionSupport {
private static final long serialVersionUID = 1L;
//{"urlsList":[{"id":"1","sort":"1"},{"id":"12","sort":"2"},{"id":"14","sort":"3"},{"id":"13","sort":"4"},{"id":"15","sort":"5"},{"id":"16","sort":"6"},{"id":"17","sort":"7"}]}
//Action中的"urlsList" 对应 前台页面的JSON对象中的"urlsList"
//urlsList一定要有get和set方法,struts会自动把接受到的JSON对象通过get和set注解到Java对象中
List<UrlsVO> urlsList;//接受前台JSON对象
public List<UrlsVO> getUrlsList() {
return urlsList;
}
public void setUrlsList(List<UrlsVO> urlsList) {
this.urlsList = urlsList;
}
public String saveUrlsList(){
//测试数据
for(UrlsVO urlsVO:urlsList){
System.out.println(urlsVO.getId()+":"+urlsVO.getSort());
}
//往前台输出JSON对象
JSONObject data=new JSONObject();
data.put("data", "保存成功!!!");
try {
HttpServletResponse response=ServletActionContext.getResponse();
response.setContentType("application/json;charset=UTF-8");
response.setHeader("Charset","UTF-8");
PrintWriter out=response.getWriter();
out.write(data.toString());
out.flush();
out.close();
} catch (IOException e) {
e.printStackTrace();
}
return "";
}
}