EXT+DWR+SPRING的记录
其实我真心不想用EXT(个人认为EXT对程序员本身提高没有好处),虽然做过的这些项目很早就开始使用EXT,不过自己开发的模块还是尽量不去使用它。最近实在没办法了= =,为了整个系统界面统一,硬着头皮用吧~。一个列表的例子(EXT+DWR+SPRING),记录一下,以后EXT用的最多的还是列表~
列表用到Ext.data.DWRProxy类,需要引入:
<script type="text/javascript" src="ext3/dwrproxy.js"></script>下面为前端的JS代码,其实网络提供的例子也很多了,不过大多为JsonReader,这里用的是ListRangeReader,基本代码都是大同小异:
// 关键对象: // Ext.data.HttpProxy 创建访问服务端的代理 // Ext.data.Store 数据存储器 // Ext.grid.ColumnModel gridPanel呈现时,显示的列集合 // Ext.PagingToolbar gridPanel分页 // Ext.grid.GridPanel 数据呈现 /** ******************自动行号******************* */ var rownumber = new Ext.grid.RowNumberer(); /** ******************每页显示数量******************* */ var gridPageSize = 15; /** ******************主页面******************* */ var nav = null; /** ******************搜索表单的下拉列表******************* */ var arrayStore_data_19 = { zblxData : [['1', '交通工具'], ['2', '勘察工具'], ['3', '通讯工具'], ['4', '执法用品'], ['4', '其它']], syData : [['1', '是'], ['2', '否']] } var arrayStore_19 = { zblxStore : new Ext.data.ArrayStore({ data : arrayStore_data_19.zblxData, fields : ['id', 'name'] }), syStore : new Ext.data.ArrayStore({ data : arrayStore_data_19.syData, fields : ['id', 'name'] }) } /** ******************查询过滤******************* */ var filter = { filters : new Array(), getSearchExpressions : function() { var expressions = new Array(); // 遍历表单设置查询项 var form = document.forms[0]; for (var i = 0; i < form.length; i++) { var element = form[i]; if (element != '' && element != null && element.value != "" && element.value != null) { // 再过滤一下查询项 if (element.name == "zbmc" || element.name == "zblb" || element.name == "zbxh" || element.name == "sfsh" || element.name == "syr" || element.name == "jg") { expressions.push({ name : element.name, // op : 'eq', op : 'like', stringValue : '%' + element.value + '%' }); } } } filter.filters = expressions; }, setFilter : function(proxy, params) { filter.getSearchExpressions(); var args = new Array(); if (filter.filters != null) { for (var i = 0; i < filter.filters.length; i++) { args.push(filter.filters[i]); } } params.args = [args]; } } /** ******************数据 需要引入 dwrproxy.js******************* */ var store_19 = function() { var proxy = new Ext.data.DWRProxy(xzzfZfzbDwrService.getXzzfList, true); proxy.on('beforeload', function(proxy, params) { filter.setFilter(proxy, params) }, this); // 列准备 var listType = Ext.data.Record.create([{ name : "id", type : "int" }, { name : "ctime", mapping : "ctime", type : "string" }, { name : "etime", mapping : "etime", type : "string" }, { name : "jg", mapping : "jg", type : "string" }, { name : "sfsh", mapping : "sfsh", type : "string" }, { name : "syr", mapping : "syr", type : "string" }, { name : "userid", mapping : "userid", type : "string" }, { name : "zbjj", mapping : "zbjj", type : "string" }, { name : "zblb", mapping : "zblb", type : "string" }, { name : "zbmc", mapping : "zbmc", type : "string" }, { name : "zbxh", mapping : "zbxh", type : "string" }]); var ds = new Ext.data.Store({ proxy : proxy, reader : new Ext.data.ListRangeReader({ id : 'id', root : "data", totalProperty : 'totalSize' }, listType), // true为后台排序,如果是false只在前台获取的数据排序 remoteSort : true }) ds.setDefaultSort("etime", "desc"); return { getStore : function() { return ds; } } } var store = new store_19(); var ds = store.getStore(); /** ******************列表******************* */ var list_19 = function() { // 标题处理 function titleFormater(value, metadata, record, rowIndex, colIndex, store) { if (value == '') { value = '无标题' } value = '<a href="../editPre/' + record.id + '" title="' + value + '">' + value + '</a>'; return value; } var columnModel = new Ext.grid.ColumnModel([rownumber, { header : '装备名称', align : 'center', width : 220, sortable : true, dataIndex : 'zbmc', renderer : titleFormater }, { header : '装备类别', align : 'center', sortable : true, dataIndex : 'zblb' }, { header : '装备序号', align : 'center', width : 220, sortable : true, dataIndex : 'zbxh' }, { header : '是否使用', align : 'center', sortable : true, dataIndex : 'sfsh' }, { header : '使用人', align : 'center', sortable : true, dataIndex : 'syr' }, { header : '使用机构', align : 'center', sortable : true, dataIndex : 'jg' }]); columnModel.defaultSortable = true; return { getColumnModel : function() { return columnModel; } } } var list = new list_19(); var cm = list.getColumnModel(); /** ******************Panel******************* */ var panel_19 = function() { var listgrid = new Ext.grid.GridPanel({ store : ds, cm : cm, autoHeight : true, autoWidth : true, bodyStyle : 'width:100%', stripeRows : true, border : false, loadMask : { msg : '数据载入中...' }, tbar : new Ext.PagingToolbar({ pageSize : gridPageSize, store : ds, displayInfo : true, displayMsg : '执法装备列表 {0} - {1} 共 {2} 条', emptyMsg : "没有记录", firstText : "首页", lastText : "末页", nextText : "下一页", prevText : "上一页", refreshText : "刷新", afterPageText : '页 共{0}页', beforePageText : '第' }), bbar : new Ext.PagingToolbar({ pageSize : gridPageSize, store : ds, displayInfo : true, displayMsg : '执法装备列表 {0} - {1} 共 {2} 条', emptyMsg : "没有记录", firstText : "首页", lastText : "末页", nextText : "下一页", prevText : "上一页", refreshText : "刷新", afterPageText : '页 共{0}页', beforePageText : '第' }) }); var mainPanel = new Ext.Panel({ collapsible : true, title : '执法装备列表', items : [listgrid] }); return { getPanel : function() { return mainPanel; } } } var panel = new panel_19(); var mainPanel = panel.getPanel(); /** ******************按钮函数******************* */ var buttonAction = { search : function() { ds.load({ params : { start : 0, limit : gridPageSize } }); }, add : function() { window.location.href = "../addPre/"; }, reset : function() { nav.form.reset(); } } /** ******************查询表单******************* */ var form_19 = { // 第一行表单 items1 : { // 行1 layout : "column", // 从左往右的布局 items : [{ columnWidth : .3, // 该列有整行中所占百分比 layout : "form", // 从上往下的布局 items : [{ xtype : "textfield", fieldLabel : "装备名称", name : 'zbmc', width : 100 }] }, { columnWidth : .3, layout : "form", items : [{ xtype : "combo", fieldLabel : "装备类别", name : 'zblb', store : arrayStore_19.zblxStore, valueField : 'name', displayField : "name", mode : "local", width : 100 }] }, { columnWidth : .3, layout : "form", items : [{ xtype : "textfield", fieldLabel : "装备序号", name : 'zbxh', width : 100 }] }] }, // 第二行表单 items2 : { // 行2 layout : "column", // 从左往右的布局 items : [{ columnWidth : .3, // 该列有整行中所占百分比 layout : "form", // 从上往下的布局 items : [{ xtype : "combo", fieldLabel : "是否使用", name : 'sfsh', store : arrayStore_19.syStore, valueField : 'name', displayField : "name", mode : "local", width : 100 }] }, { columnWidth : .3, layout : "form", items : [{ xtype : "textfield", fieldLabel : "使用人", name : 'syr', width : 100 }] }, { columnWidth : .3, layout : "form", items : [{ xtype : "textfield", fieldLabel : "所属机构", name : 'jg', width : 100 }] }] }, // 第二行按钮 button : { bodyStyle : 'padding:0px', buttonAlign : 'center', buttons : [{ text : '开始查询', handler : function() { buttonAction.search(); } }, { text : '清空查询项', handler : function() { buttonAction.reset(); } }, { text : '添加装备', handler : function() { buttonAction.add(); } }] } } Ext.onReady(function() { // 主页面 nav = new Ext.form.FormPanel({ title : '执法装备管理', frame : true, border : true, x : 0, y : 0, renderTo : Ext.getBody(), items : [form_19.items1, form_19.items2, form_19.button, // 行4 mainPanel] }); // 第一次刷新数据 buttonAction.search(); }); // xzzfZfzbDwrService.getXzzfList(null, 0, 10, null, result); // function result(data) { // alert(data.totalSize); // alert(data.data); // alert(data.data[0]); // alert(data.data[0].zbmc); // alert(data.data[0].zblb); // alert(data.data[0].zbxh); // alert(data.data[0].sfsh); // alert(data.data[0].syr); // alert(data.data[0].jg); // }
关于这段JS的细节记录:
var rownumber = new Ext.grid.RowNumberer();EXT本身的序列生成器,用于列表。
gridPageSize 每页显示的列表条数。
filter用于过滤表单并生成查询项,查询项本身的生成方法有很多,这里只是我的写法。此查询队列会被DWRProxy提交到后台。这里的查询队列中每个查询对象有三个属性:name,op,stringValue,后台需要根据这三个属性生成相应的查询语句。
之后便是Ext.data.Store,需要设置三个对象:proxy,类似于new Ext.data.DWRProxy(xzzfZfzbDwrService.getXzzfList, true);,xzzfZfzbDwrService.getXzzfList就是DWR注册的可调用的方法。reader : new Ext.data.ListRangeReader 为服务端返回的数据,设置返回数据的根root : "data",数据的长度大小totalProperty : 'totalSize',数据列的对应mapping:listType,listType需要对应为你返回的bean中的name。
其中remoteSort : true,true为后台排序,每次点击标题头都会从后台根据排序方式重新获取数据,如果是false只在前台获取的当前列表的数据排序。
ds.setDefaultSort("etime", "desc");为默认的排序方法,此方法会用参数传递到后台。
proxy.on('beforeload', function(proxy, params) 表示在load数据前做的相关操作,这里的操作就是设置查询项。
之后便是设置GridPanel,包括标题头ColumnModel,前进后退栏PagingToolbar,整个查询的表单FormPanel,这块没什么说的,照着写就行了。
第一次打开页面执行buttonAction.search();来获取初始数据。
下边是后台的写法
首先需要写一个EXT的ListRange BEAN 并在dwrServlet.xml中注册,Ext.data.DWRProxy接收返回的数据类型便是此BEAN。如上所述的(xzzfZfzbDwrService.getXzzfList),需要两个基本对象,totalSize和data。
public class ListRange implements Serializable { private Object[] data; private int totalSize public Object[] getData() { return data; } public void setData(Object[] data) { this.data = data; } public int getTotalSize() { return totalSize; } public void setTotalSize(int totalSize) { this.totalSize = totalSize; } }
还需要写一个查询项的bean,类似于:
public class Expression { private String name; private String op; private Object value; get set......
之后就是具体的外部调用的xzzfZfzbDwrService.getXzzfList的写法,类似于:
public ListRange getXzzfList(Expression[] expressions, int startPosition, int maxResults, String orderBy) throws Exception { //startPosition及maxResults是EXT根据当前页数及每页显示的条数提交过来的数据。 //expressions为遍历的表单后的查询项 如上所述此查询队列每个查询对象有三个属性 name,op,stringValue //可以根据这三个属性循环遍历出队列的查询语句例如 Object query = null; for (int i = 0; i < expressions.length; i++) { String name = expression.getName(); String op = expression.getOp(); String value = expression.getValue(); //创建查询语句 query = ....; } //orderBy为EXT中DS设置的ds.setDefaultSort("etime", "desc"); 如果你Ext.data.Store的remoteSort设置为true,则每次点击标题头也会根据标题头的dataIndex的值传入类似于 "dataIndex desc"的排序语句。 //orderBy为一个简单的字符串如"etime desc",可以用切字符串的方法对排序进行进一步处理,或者直接使用这个排序字符,下边是一个进一步处理的例子: int pos = orderBy.indexOf(' '); String field = orderBy.substring(0, pos); String dir = orderBy.substring(pos + 1); if ("asc".equalsIgnoreCase(dir)) { ...... } else { ...... } //之后便是获取ListRange的两个基本数据 int count = count(query); //注意此查询出的bean需要在dwr中注册 List<bean> items = find(orderBy, startPosition, maxResults, query); //封装返回 ListRange result = new ListRange(); result.setTotalSize(count); result.setData(items.toArray()); return result; }
最后就是注册Spring的dwrServlet.xml,包括注册外部调用的方法,需要封装的BEAN,这块就不细说了。别忘记还需要注册返回到EXT中的ListRange。
<dwr:convert class="ListRange" type="bean"/> <dwr:convert class="YouBean" type="bean"/>
效果图:
