您的位置:首页 > Web前端 > JavaScript

ExtJs如何通过JSON与后台通信

2016-08-24 09:27 507 查看


ExtJs如何通过JSON与后台通信

 
How tocommunicate with server via JSON
 
 
引言
 
EXT技术对提升用户体验有着先天的优势,很多机构和个人都开始学习EXT技术,截止今天EXT CORE 3.0 也已经发布,EXTJS 3.0 指日可待。虽然性能越来越让人担忧。。。
 
无论用多么惊天地泣鬼神的前台技术,与后台的通信总是必须的。本文就目前手头上有的资料和经验来大概阐述一下EXTJS和后台通信这点事。
 
 
为什么要用JSON?
 
 选中JSON不是一拍脑门子的事。EXTJS也不是只支持JSON。目前常用的不外乎下面几种通信方式:
 
 
1. 动态语言文件周转,如JSP

用JSP一类的动态语言文件中转数据无疑是传递数据比较简单的一种,但是不好传递对象。随便举个用Session传递数据的例子。例如:

varUserName= <%=session.getAttribute("user")%>;

if(UserName==null){

location.href = 'login.jsp';

}

缺点就是不能方便的传递对象。不那么舒服,EXT的不彻底。还在混杂使用JSP这种相比与EXT来说老掉牙的东西。 当然,如果项目条件不允许,或者不需要做成彻底的AJAX OnePage应用。这种方式还是可以解决很多迫在眉睫的问题的。(我是彻底的One Page 狂热者^.^)
 
2. JSON

JSON是和JavaScript门当户对的数据传输方式,所以用起来会很舒服。而且他可以很方便的传递对象,EXT也对JSON支持的很全面。所有的数据传递需求他都可以胜任。现在第三方的JSON框架也很成熟。
 
3. XML

EXTJS本身是提供对XML类型数据的解析功能的,和JSON一样。 官方的示例程序也有专门演示XML数据通信的。个人感觉和JSON是同一个级别的,也是比较推荐的方式。
 
4. 文本

异步调用返回的东西是文本,说白了AJAX就是靠文本传输数据的,无论JSON还是XML,他都是文本。所以文本很牛的。如果弄好了,自己定义一个传输格式也不是不可以。一般不复杂的东西,比如传个标记,传个string什么的。没必要用JSON,用文本就很好用。

缺点已经说了,就是无法胜任稍复杂的通信需求。
 
所以目前看来就在JSON和XML中选择一个了。XML以后再表,我们现在主要表JSON。
 
通信过程
 
 
 
从后台到前台
 
看一下通信过程中的图,其中对象我们已经有了,也就是你想要传递的东西。剩下的,就是后台如何把对象转换成JSON,以及前台如何把JSON再解析为对象了。我们先来看后台如何把对象转换成JSON。
 
首先要隆重登场的是我自己改写的一个根据LIST生成JSON的类。其实这类简单的要死。所以他只能胜任把LIST转成JSON的工作。而且还有一个局限,至于是什么局限,我们慢慢说。
 
先看代码:
 
//yueue修改的轻量级JSON类
 
package Extest;

import java.util.ArrayList;
 
 
public class Json {
 
 
public static void main(String[] args) {
 
 
}

public String singleInfo="";

public Integer total=0;

protected boolean _success=true;

protected String _error="";

protected ArrayList arrData=new ArrayList();

protected ArrayList dataItem=new ArrayList();

public String getError() {

return _error;

}

public void setError(String error) {

if(!error.equals(""))this._success=false;

this._error = error;

}

public boolean getSuccess() {

return _success;

}

public void setSuccess(boolean success) {

if(success) this._error="";

this._success = success;

}

public Json()

{

}

public void reSet()

{

arrData.clear();

dataItem.clear();

}

public void addItem(String name,String _value)

{

dataItem.add(name);

dataItem.add(_value);

}

//一个数组添加完毕,一个新的数组开始

public void addItemOk()

{

arrData.add(dataItem);

dataItem=new ArrayList();

}

public String ToString()

{

StringBuilder sb=new StringBuilder();

sb.append("{");

sb.append("\"total\":");

sb.append(total.toString()+",");

sb.append("\"datas\":");

sb.append("[");

int ad=arrData.size();

for(int i=0;i<ad;i++)

{

ArrayList arr=(ArrayList)(arrData.get(i));

sb.append("{");

int t=arr.size();

for(int j=0;j<t;j+=2)

{

if(j==t) break;

sb.append("\"");

sb.append(arr.get(j).toString());

sb.append("\"");

sb.append(":");

sb.append("\"");

sb.append(arr.get(j+1).toString());

sb.append("\"");

if(j<t-2) sb.append(",");

}

sb.append("}");

if(i<ad-1) sb.append(",");

}

sb.append("]");

sb.append("}");

return sb.toString();

}

}
 
 
代码不长。下面我们看看怎么用这个东西把一个LIST转成JSON
 
 
Json js = new Json();

while (rs.next())

{

js.addItem("ID", rs.getString("ID"));

js.addItem("Code", rs.getString("Sheet_Code"));

js.addItem("Consignee", rs.getString("Sheet_Consignee"));

js.addItem("Tone", rs.getString("Sheet_Tone"));

js.addItem("Date", rs.getString("Sheet_Date"));

js.addItem("Cash", rs.getString("Sheet_Cash"));

js.addItem("Station", rs.getString("Sheet_Station"));

js.addItem("Class", rs.getString("Sheet_Class"));

js.addItemOk();

}
 
System.out.print(js.outputString());
 
 
其中rs是一个ResultSet ,里面放的是从数据库里读取的数据。
 
其中每次 addItem() 都向JSON提交了一个字段(属性),当字段提交完毕,执行addItemOk()方法,就会创建条完整的记录(对象) , 当你循环执行这个流程,就提交了多条记录(对象),最后的最后, outputString() 方法将你前面提交的所有记录(对象)转化为JSON并打印出来。你可以对比代码看看最后输出来的JSON到底是个什么样子。有助于你理解JSON。
 
 
上面的这个类看起来似乎不错。实际上这个类几乎没有大的用途。因为他只能处理简单的对象,他遇到任何对象都会调用其toString 方法试图获得代表这个对象的字符串,然后储存并转化。当然,如果是String , Integer , Double ,等类型自然没有问题,因为这些对象可以不失真的转化为String。而遇到一个复杂对象,比如一个由Hibernate生成的对象,他就无能为力了。他不能自动遍历对象下面的所有属性,并一一转换。
 
 
那么怎么解决呢? 答案是用强大的第3方类库,比如JSON-Lib 或者 org.json包
 
 
JSON-lib 是一个封装了常用的JSON业务的第3方类库,很强,很大。
 
使用JSON-lib 还需要很多特定版本的包来支持(很烦)。
 
具体的安装,还有需要什么支持包,去jsonlib网站上看吧。
 
 
下面看一个项目中常用的JSON-Lib使用例子。(在ACTION中的代码)
 
 
 

try{ 

PrintWriter out = response.getWriter();

UserInfo userInfo = (UserInfo)request.getSession().getAttribute("userinfo"); //从session中得到用户信息对象

String tempStr = "{\"Datas\":"+JSONSerializer.toJSON(theList,config).toString()+"}";

out.print(tmpStr);

return null;

}catch(Exception ex){

ex.printStackTrace();

return null;

}
 
 
很简单,使用JSON-Lib转化的工作就在String tempStr = "{\"Datas\":"+JSONSerializer.toJSON(theList,config).toString()+"}";

这行搞定了。然后输出就可以了。
 
但是,这里有3个问题:
 
1. 会有可能出现乱码
 
2. 会出现环,比如,对象A中包含B,而对象B中又再次包含A,于是出现了无限循环的环路。这个时候JSON-LIB会报一个net.sf.json.JSONException: There is a cycle in the hierarchy的错误。
 
3. 会出现日期问题,因为JAVA中日期属于一个复杂对象,JSON-Lib会把他当做一个复杂对象去解析,得到的结果就不是你要的 2009-01-01 这样的字符串了
 
解决方法:
 
1. 请参见我的BLOG : 《Extjs Ajax 乱码问题解决方案》
 
2. 请参见我的BLOG: 《json-lib出现There is a cycle in the hierarchy解决办法》
 
3. 对JSON-LIB进行设置 config.registerJsonValueProcessor(Date.class,new DateJsonValueProcessor("yyyy-MM-dd")); //date processor register
 
所以,最后,这段转换对象的代码最后变成
 
 
response.setContentType("text/html");

response.setCharacterEncoding("utf-8");
 
try{ 

PrintWriter out = response.getWriter();

UserInfo userInfo = (UserInfo)request.getSession().getAttribute("userinfo"); //从session中得到用户信息对象
 
JsonConfig config = new JsonConfig();

config.setIgnoreDefaultExcludes(false); 

config.setCycleDetectionStrategy(CycleDetectionStrategy.LENIENT); 

config.registerJsonValueProcessor(Date.class,new DateJsonValueProcessor("yyyy-MM-dd")); //date processor register

String tempStr = "{\"Datas\":"+JSONSerializer.toJSON(theList,config).toString()+"}";

out.print(tmpStr);

return null;

}catch(Exception ex){

ex.printStackTrace();

return null;

}
 
 
可以访问一下ACTION或者SERVLET, 看看结果了
 
 
现在把对象转化为JSON没问题了。剩下的是前台如何把JSON转化成对象了。
 
其实这部分工作EXT基本全都做了。EXT主要的数据接收和储存靠Store 。 EXT提供有JSONStroe 用来处理json 。 这部分的工作基本不直接接触JSON ,而是使用EXT。
 

 
//Grid Store from servlet

var store = new Ext.data.JsonStore({
url:'/ctams/plan/monthTransportPlan.do?method=findMonthTransportPlan',

root:'Datas',

totalProperty: 'TotalRecords',

fields:["mtpId",

"mtpDate", 

"mtpAcceptnum",

"mtpPlannum",

"mtpCarriagenum",

"mtpTunnage",

"mtpTrainnum",

"mtpFormernum",

"mtpFormertunnage",

"mtpFormertrainnum",

"mtpSwapload",

"mtpEndharbor",

"mtpAlreadyuse",

"mtpFlag",

"mtpRemark",

{name:'mpId',mapping:'monthPlan.mpId'}

],

baseParams:{

planDate:txtSearchText.getValue(),

planType:'42',

conName:''

}

});
 
 
 
 
从前台到后台
 
 
 
目前我接触到系统往前台发送数据主要通过HTTP参数发送。
 
更高级一些的就是打包成json,再发回服务器
 
见我的BLOG 《如何把一个对象转换为JSON并将其发送到服务器》
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

分类: 前端表现/Web/ExtJs

好文要顶 关注我 收藏该文 

 






yueue
关注 - 0
粉丝 - 8

+加关注

0

0

« 上一篇:ExtJs
及 Ajax 乱码解决方案
» 下一篇:EXT如何把一个对象转换为JSON并将其发送到服务器

posted @ 2010-02-22 09:21 yueue 阅读(7483)
评论(4) 编辑 收藏

评论列表

  
#1楼 2010-02-22
09:55 tubo  

很早之前写的文章吧,现在3.1都发布了
支持(0)反对(0)

  
#2楼 2010-02-22
10:46 show_show  

很老的文章了啊
支持(0)反对(0)

  
#3楼 2010-02-22
11:04 腾讯CEO马化腾  

嗯一眨眼EXT变成3.1了,真怀念自己收集JS小效果的童年
支持(0)反对(0)

  
#4楼 2010-02-22
11:35 Dreampuf  

找不到<<json-lib出现There is a cycle in the hierarchy解决办法>>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: