jQuery学习之:jqGrid表格插件——从Struts2获得数据

之前谈到了jqGrid与Serlvet/JSP集成,实际上就是Servlet按jqGrid对数据的要求返回相应的数据,Servlet中是通过PrintWriter输出数据的,那时,我们用到了json-lib来构建Json数据。现在来谈谈jqGrid如何与Struts2集成。 
对于Struts2,同样需要按jqGrid的要求返回相应的json数据格式。当然,我们可以在Struts2的Action中通过返回null来干Servlet一样的事情,这样也能够同Servlet一样实现与jqGrid集成。然而,此时Struts2实际上相当于没有。既然用到了Struts2,我们就应该用Struts2为我们提供的方法。而且,在Struts的Action中应该尽量避免使用request之类的Servlet对象,用Struts2更是如此。在struts1.x中,request直接就有的,因而在开发中总会有人“打着struts的旗帜,干着Servlet的勾当”。我们知道,request等是依赖于Servlet容器的,Struts2把这些屏蔽了,Struts2的Action可以直接是POJO,因而我们更不应该违反Struts2的设计原则,硬是去“干Servlet的勾当”。闲话不说,开始咱们的正题。 
在Struts2的jar包中,有一个struts2-json-plugin.jar,它就是用于处理json数据的(Struts2提供了很多插件),我们就是应用它来实现struts2与jqGrid的集成。 
1、效果图:
jQuery学习之:jqGrid表格插件——从Struts2获得数据 
2、代码与解释: 
HTML代码:
<body>

<tableid="gridTable"></table>

<divid="gridPager"></div>

</body>
JavaScript代码:
$(function()

{

$("#gridTable").jqGrid({

url:'json/jqgrid.action',

datatype:"json",

height:250,

colNames:['编号','用户名','性别','邮箱','QQ','手机号','出生日期'],

colModel:[

{name:'id',index:'id',sorttype:"int"},

{name:'userName',index:'userName',

{name:'gender',index:'gender',

{name:'email',index:'email',;string"},

{name:'QQ',index:'QQ',;

{name:'mobilePhone',index:'mobilePhone',;

{name:'birthday',index:'birthday',sorttype:"date"}

],

sortname:'id',

sortorder:'asc',

viewrecords:true,

rowNum:10,

rowList:[10,20,30],

jsonReader:{

root:"dataRows",//数据行(默认为:rows)

page:"curPage",//当前页

total:"totalPages",//总页数

records:"totalRecords",//总记录数

repeatitems:false//设置成false,在后台设置值的时候,可以乱序。且并非每个值都得设

},

prmNames:{rows:"page.pageSize",page:"page.curPageNo",sort:"page.orderBy",order:"page.order"},

pager:"#gridPager",

caption:"jqGrid与Struts2集成"

}).navGrid('#gridPager',{edit:false,add:false,del:false});

})

注意,JavaScript代码与Servlet例子中的有点不一样,主要是:jsonReader参数,另外增加了prmNames参数。每一项的是什么意思下面Java代码的注释中有详细说明。 
Java代码:
package com.polaris.jqgrid.struts2;

importjava.util.ArrayList;

importjava.util.List;

importjava.util.Map;

importcom.opensymphony.xwork2.ActionSupport;

importcom.polaris.jqgrid.util.Page;

/**

*<p>

*该类是所有需要返回json数据的Action的<b>抽象基类</b>。在展示数据时,使用了jQuery的插件jqGrid,

*它对返回的json数据格式有一定的要求。该基类就处理了这些统一的格式要求。

*需要返回json格式数据被jqGrid使用的,应该继承该类。<br/>

*<b><fontcolor='red'>注意:所有子类应该实现以下get方法,并只简单的返回相应的属性值。</font></b>

*<ul>

*<li>{@linkJsoBaseAction#getTotalPages()}</li>

*<li>{@linkJsoBaseAction#getCurPage()}</li>

*<li>{@linkJsoBaseAction#getTotalRecords()}</li>

*<li>{@linkJsoBaseAction#getDataRows()}</li>

*</ul>

*之所以将这些get方法定义为抽象的,是因为struts2的json插件只会序列化Action类,而不会序列化其父类。

*</p>

*

*<p><fontcolor='red'>

*继承该类的Action方法,除了搜索(它需要返回JSON数据,因此可以返回SUCCESS),其他操作都应该返回null而不是SUCCESS之类的。

*这意味着struts配置中,result什么也不用配,即没有相应的视图资源——这是AJAX请求。

*</font></p>

*

*<p>

*该类定义了以下几个字段:totalPages、curPage、totalRecords和dataRows。

*这几个字段是jqGrid格式的要求,而此处是自定义的。因此,在配置jqGrid接收服务器

*返回的数据格式时,应该配置成这几个名字。(因为默认名字不是这样的,默认名字为:page,total,records,rows)

*当然,也可以通过@JSON注解来指定与默认一样的名字

*</p>

*

*<p>

*另外一个字段page,则是一个分页类。因为jqGrid会向服务器端传递分页参数,

*用一个分页类接收这些参数。同样,为使Struts能够为page赋值,需要修改jqGrid默认的分页参数名。

*jqGrid默认分页名为:(默认定义在options参数中的prmNames数组中)

*<ul>

*<li>page->显示第几页</li>

*<li>rows->每页显示几条记录</li>

*<li>sidx->排序字段</li>

*<li>sord->排序方式(asc/desc)</li>

*</ul>

*应用中应该根据{@linkcom.polaris.jqgrid.util.Page}类中的定义设置。设置为:

*prmNames:{rows:"page.pageSize",page:"page.curPageNo",sort:"page.orderBy",order:"page.order"}

*

*prmNames数组的默认值为:

*prmNames:{page:"page",rows:"rows",sort:"sidx",order:"sord",search:"_search",nd:"nd",npage:null}

*</p>

*

*@authorxuxinhua

*@version1.0

*/

@SuppressWarnings("unchecked")

publicabstractclassJsonBaseActionextendsActionSupport

{

privatestaticfinallongserialVersionUID=1L;

/**

*该属性专门用于接收删除的数据的ID(主键)。注意,当支持一次删除多记录时,id的值是通过','号分隔的多个

*/

protectedStringid;

/**

*分页类

*/

protectedPagepage=newPage();

/**

*以下属性用于序列化成json格式的数据。名称不能改。如果要改,客户端页面对应的地方也要改;

*或通过@JSON来指定序列化的名字

*/

/**

*总页数

*/

protectedinttotalPages;

/**

*显示第几页

*/

protectedintcurPage;

/**

*总记录数

*/

protectedinttotalRecords;

/**

*保存实际的数据

*/

protectedList<Map<String,Object>>dataRows=newArrayList<Map<String,Object>>();

publicJsonBaseAction(){

super();

}

publicPagegetPage(){

returnpage;

}

publicvoidsetPage(Pagepage){

this.page=page;

}

publicvoidsetId(Stringid){

this.id=id;

}

publicStringgetId(){

returnid;

}

publicabstractintgetTotalPages();

publicvoidsetTotalPages(inttotalPages){

this.totalPages=totalPages;

}

publicabstractintgetCurPage();

publicvoidsetCurPage(intcurPage){

this.curPage=curPage;

}

publicabstractintgetTotalRecords();

publicvoidsetTotalRecords(inttotalRecords){

this.totalRecords=totalRecords;

}

/**

*注意该方法的返回值:List。实际上包含了实际的数据,

*而这些数据是放在Map<String,Object>中的。

*因而,子类在action方法如:execute中,应该构建一个

*Map<String,Object>对象,将数据放入其中,并把该对象放入

*List中。

*@return

*/

publicabstractList<Map<String,Object>>getDataRows();

publicvoidsetDataRows(List<Map<String,Object>>dataRows){

this.dataRows=dataRows;

}

}

这个类是一个抽象基类,为了方便扩展而设计的。需要返回json数据(使用jqGrid插件)的Action应该继承该类。这个类是我为公司写的一个类,拿出来与大家分享。

实际处理JSON数据的Action类代码:
package com.polaris.jqgrid.struts2;

importjava.util.HashMap;

importjava.util.List;

importjava.util.Map;

/**

*该Struts2向客户端返回一个json对象。为了简便,数据不是从数据库获得的。

*jqGrid默认期望返回的json对象格式要求如下:

*{"page":"1","total":"2","records":"13",

*"rows":[

*{id:"1",cell:["1","polaris","男","polaris@gmail.com","772618379","18329382732","1985-10-2"]},

*{id:"2",cell:["2","张三","女","zhangsan@163.com","272618382","15329382732","1986-10-12"]},

*{id:"3",cell:["3","王五","女","wangwu@yahoo.com","172635372","13329389832","1987-12-21"]},

*{id:"4",cell:["4","赵六","男","zhaoliu@sina.com","372618332","18929343731","1988-09-22"]}

*]

*}

*当然,在js中,可以通过jqGrid的jsonReader属性来修改默认格式

*因为默认的格式,rows的数据要求顺序不能变,且每个字段都得有值(空也得有"")。因而,

*在jsonReader中定义repeatitems:false。这样,rows就变成了:

*"rows":[

*{id:"1",userName:"polaris",gender:"男",email:"polaris@gmail.com",QQ:"772618379",mobilePhone:"18329382732",birthday:"1985-10-2"]},

*{id:"2",userName:"徐新华",gender:"男",email:"xh.xu@163.com",QQ:"272618382",mobilePhone:"15329382732",birthday:"1986-10-12"]},

*{id:"3",userName:"王五",gender:"女",email:"wangwu@yahoo.com",QQ:"172635372",mobilePhone:"13329389832",birthday:"1987-12-21"]},

*{id:"4",userName:"赵六",gender:"女",email:"zhaoliu@sina.com",QQ:"372618332",mobilePhone:"18929343731",birthday:"1988-09-22"]}

*]

*@authorxuxinhua

*

*/

publicclassJqGridForJSONActionextendsJsonBaseAction

{

privatestaticfinallongserialVersionUID=132383828833L;

/**

*该方法得到数据并构造json对象以便返回给客户端

*@return

*@throwsException

*/

publicStringexecute()throwsException

{

//构建几条数据

inti=0;

for(i=0;i<4;++i)

{

//定义一个Map<String,Object>存放一行行数据。(跟从Servlet获得数据类似,只不过此处不需要用json-lib)

Map<String,Object>row=newHashMap<String,Object>();

row.put("id",i);

if(i%2==0)

{

row.put("userName","polaris");

row.put("gender","女");

}

else

{

row.put("userName","徐新华");

row.put("gender","男");

}

row.put("email","polaris@gmail.com");

row.put("QQ","772"+i+"1837"+i);

row.put("mobilePhone","132"+i+"1837"+i+"3"+i);

row.put("birthday","198"+i+"-10-"+"1"+i);

dataRows.add(row);

}

//给另外三个返回参数设值

setTotalPages(1);//总页数

setCurPage(1);//当前页

setTotalRecords(i);//总记录数

returnSUCCESS;

}

/*

*以下getter方法必须实现,struts2-json插件会将这些getter方法序列化,以便输出json对象。

*这些getter方法只需返回相应的属性即可。如getCurPage应该返回curPage

*(curPage在JsonBaseAction中有定义)

*/

@Override

publicintgetCurPage()

{

returnthis.curPage;

}

@Override

publicList<Map<String,Object>>getDataRows()

{

returnthis.dataRows;

}

@Override

publicintgetTotalPages()

{

returnthis.totalPages;

}

@Override

publicintgetTotalRecords()

{

returnthis.totalRecords;

}

}

注意看注释。

struts.xml的配置:
<constant name="struts.i18n.encoding" value="utf-8"></constant>

<packagename="json"namespace="/json"extends="json-default">

<actionname="jqgrid"class="com.polaris.jqgrid.struts2.JqGridForJSONAction">

<resulttype="json"></result>

</action>

</package>

说明:1)设置字符编码,否则会乱码;2)package要继承自json-default,json-default在struts2-json-plugin中有定义;3)result的type必须为json,表示返回数据类型为json,然而视图映射留空(即result不能对应一个视图)

web.xml的struts2核心过滤器的配置:
<filter>

<filter-name>struts2</filter-name>

<filter-class>

org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter

</filter-class>

</filter>

<filter-mapping>

<filter-name>struts2</filter-name>

<url-pattern>/*</url-pattern>

</filter-mapping>

你可能会发现,此处配置的过滤器类名和网上很多地方说的不一样。的确,我用的struts2是2.1.8。自从2.1.3开始,原来的过滤器FilterDispatcher被标注为:Deprecated

结语: 
至此jqGrid告一段落,不好之处请指正。如有什么问题,可以联系我,我们一起讨论。
 
由于很多人问我要例子的源代码,polaris也都发给了大家,然而有时候很晚才看到,发的会有点晚。鉴于此,特提供下载polaris的jqGrid的例子代码,谢谢大家的支持!
 
可以到:http://www.beijixing001.com/?p=406文章结尾下载我的例子代码。

相关推荐