以前談到了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的集成。
一、效果圖:
二、代碼與解釋:
HTML代碼:
<
body
>
<
table
id
="gridTable"
>
</table>
<
div
id
="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;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import com.opensymphony.xwork2.ActionSupport;
import com.polaris.jqgrid.util.Page;
/**
* <p>
* 該類是全部須要返回json數據的Action的<b>抽象基類</b>。在展現數據時,使用了jQuery的插件jqGrid,
* 它對返回的json數據格式有必定的要求。該基類就處理了這些統一的格式要求。
* 須要返回json格式數據被jqGrid使用的,應該繼承該類。<br/>
* <b><font color='red'>注意:全部子類應該實現如下get方法,並只簡單的返回相應的屬性值。</font></b>
* <ul>
* <li>{@link JsoBaseAction#getTotalPages()}</li>
* <li>{@link JsoBaseAction#getCurPage()}</li>
* <li>{@link JsoBaseAction#getTotalRecords()}</li>
* <li>{@link JsoBaseAction#getDataRows()}</li>
* </ul>
* 之因此將這些get方法定義爲抽象的,是由於struts2的json插件只會序列化Action類,而不會序列化其父類。
* </p>
*
* <p><font color='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>
* 應用中應該根據{@link com.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>
*
* @author xuxinhua
* @version 1.0
*/
@SuppressWarnings(
"unchecked")
public
abstract
class JsonBaseAction
extends ActionSupport
{
private
static
final
long serialVersionUID = 1L;
/**
* 該屬性專門用於接收刪除的數據的ID(主鍵)。注意,當支持一次刪除多記錄時,id的值是經過','號分隔的多個
*/
protected String id;
/**
* 分頁類
*/
protected Page page =
new Page();
/**
* 如下屬性用於序列化成json格式的數據。名稱不能改。若是要改,客戶端頁面對應的地方也要改;
* 或經過@JSON來指定序列化的名字
*/
/**
* 總頁數
*/
protected
int totalPages;
/**
* 顯示第幾頁
*/
protected
int curPage;
/**
* 總記錄數
*/
protected
int totalRecords;
/**
* 保存實際的數據
*/
protected List<Map<String,Object>> dataRows =
new ArrayList<Map<String,Object>>();
public JsonBaseAction() {
super();
}
public Page getPage() {
return page;
}
public
void setPage(Page page) {
this.page = page;
}
public
void setId(String id) {
this.id = id;
}
public String getId() {
return id;
}
public
abstract
int getTotalPages();
public
void setTotalPages(
int totalPages) {
this.totalPages = totalPages;
}
public
abstract
int getCurPage();
public
void setCurPage(
int curPage) {
this.curPage = curPage;
}
public
abstract
int getTotalRecords();
public
void setTotalRecords(
int totalRecords) {
this.totalRecords = totalRecords;
}
/**
* 注意該方法的返回值:List。實際上包含了實際的數據,
* 而這些數據是放在Map<String, Object>中的。
* 於是,子類在action方法如:execute中,應該構建一個
* Map<String, Object>對象,將數據放入其中,並把該對象放入
* List中。
* @return
*/
public
abstract List<Map<String, Object>> getDataRows();
public
void setDataRows(List<Map<String, Object>> dataRows) {
this.dataRows = dataRows;
}
}
這個類是一個抽象基類,爲了方便擴展而設計的。須要返回json數據(使用jqGrid插件)的Action應該繼承該類。這個類是我爲公司寫的一個類,拿出來與你們分享。java
實際處理JSON數據的Action類代碼:
package com.polaris.jqgrid.struts2;
import java.util.HashMap;
import java.util.List;
import java.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"]}
* ]
* @author xuxinhua
*
*/
public
class JqGridForJSONAction
extends JsonBaseAction
{
private
static
final
long serialVersionUID = 132383828833L;
/**
* 該方法獲得數據並構造json對象以便返回給客戶端
* @return
* @throws Exception
*/
public String execute()
throws Exception
{
// 構建幾條數據
int i = 0;
for(i=0;i<4;++i)
{
// 定義一個Map<String,Object>存放一行行數據。(跟從Servlet得到數據相似,只不過此處不須要用json-lib)
Map<String, Object> row =
new HashMap<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);
// 總記錄數
return SUCCESS;
}
/*
* 如下getter方法必須實現,struts2-json插件會將這些getter方法序列化,以便輸出json對象。
* 這些getter方法只需返回相應的屬性便可。如getCurPage應該返回curPage
* (curPage在JsonBaseAction中有定義)
*/
@Override
public
int getCurPage()
{
return
this.curPage;
}
@Override
public List<Map<String, Object>> getDataRows()
{
return
this.dataRows;
}
@Override
public
int getTotalPages()
{
return
this.totalPages;
}
@Override
public
int getTotalRecords()
{
return
this.totalRecords;
}
}
注意看註釋。web
struts.xml的配置:
<
constant
name
="struts.i18n.encoding"
value
="utf-8"
>
</
constant
>
<
package
name
="json"
namespace
="/json"
extends
="json-default"
>
<
action
name
="jqgrid"
class
="com.polaris.jqgrid.struts2.JqGridForJSONAction"
>
<
result
type
="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
apache
結語:
至此jqGrid告一段落,很差之處請指正。若有什麼問題,能夠聯繫我,咱們一塊兒討論。
因爲不少人問我要例子的源代碼,polaris也都發給了你們,如今不多上51CTO,須要的關注我微博 http://weibo.com/beijixing001,私信我。