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的集成。
 
一、效果圖:
polaris 
二、代碼與解釋:
 
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,私信我。
相關文章
相關標籤/搜索