EXT+DWR+SPRING的记录

其实我真心不想用EXT(个人认为EXT对程序员本身提高没有好处),虽然做过的这些项目很早就开始使用EXT,不过自己开发的模块还是尽量不去使用它。最近实在没办法了= =,为了整个系统界面统一,硬着头皮用吧~。一个列表的例子(EXT+DWR+SPRING),记录一下,以后EXT用的最多的还是列表~

列表用到Ext.data.DWRProxy类,需要引入:

1
<script type="text/javascript" src="ext3/dwrproxy.js"></script>

下面为前端的JS代码,其实网络提供的例子也很多了,不过大多为JsonReader,这里用的是ListRangeReader,基本代码都是大同小异:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
// 关键对象:
// 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。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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,类似于:

1
2
3
4
5
6
7
public class Expression {
 
	private String name;
	private String op;
	private Object value;
 
	get set......

之后就是具体的外部调用的xzzfZfzbDwrService.getXzzfList的写法,类似于:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
	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。

1
2
<dwr:convert class="ListRange" type="bean"/>
<dwr:convert class="YouBean" type="bean"/>

发表评论

电子邮件地址不会被公开。 必填项已用 * 标注

*

您可以使用这些 HTML 标签和属性: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="" highlight="">