19~ | Code.log - java,oracle,actionscript,php,mysql,javascript...... -

EXT+DWR+SPRING的记录

发布时间: November 2, 2011 | Tags: ext,spring,dwr | Views: 349
其实我真心不想用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"/>

效果图:

关于apache配置多域名

发布时间: February 23, 2011 | Tags: apache,mod_rewrite,VirtualHost | Views: 603

关于apache配置多域名,一般为两种方法,虚拟主机及利用mod_rewrite对URL进行重定向或伪链~

  • 虚拟主机配置方法,在httpd.conf文件最后简单添加,例如:
  • <VirtualHost www.google.com>
    	DocumentRoot usr/local/www/google
    	ServerName   www.google.com
    	#ErrorLog logs/minidx.com-error_log
    	#CustomLog logs/minidx.com-access_log common
    </VirtualHost>
     
    <VirtualHost www.baidu.com>
    	DocumentRoot usr/local/www/baidu
    	ServerName   www.baidu.com
    </VirtualHost>

    这样在访问相关域名的时候便会跳转到对应的目录,虚拟主机的最大缺点是性能消耗较大,并且似乎和APACHE用来托管静态文件、连接及负载均衡后台所用的mod_jk有冲突,所以个人不建议使用虚拟主机的方法去管理域名。

  • 利用mod_rewrite对域名进行重定向或伪链:
  • 首先需要开启mod_rewrite支持,在httpd.conf文件里搜索:

    #LoadModule rewrite_module modules/mod_rewrite.so

    去掉#号,开启mod_rewrite,继续搜索AllowOverride None更改为AllowOverride All,打开.htaccess的支持。注意AllowOverride是可以针对每个目录进行设置的,这里应该将apache DocumentRoot根路径设置为AllowOverride All:

    <Directory "/var/www/html">
        AllowOverride All
    </Directory>

    之后建立.htaccess文件放在DocumentRoot下,通过编写.htaccess来管理相关域名:

    对域名进行301重定向,.htaccess中设置:

    RewriteEngine On
    RewriteBase /
     
    RewriteCond %{HTTP_HOST} ^www.test.net.cn [NC,OR]
    RewriteCond %{HTTP_HOST} ^test.net.cn [NC]
    RewriteRule ^(.*)$ http://www.test.com/test.html$1 [R=301,L]
     
    RewriteCond %{HTTP_HOST} ^www.test.net [NC,OR]
    RewriteCond %{HTTP_HOST} ^test.net [NC]
    RewriteRule ^(.*)$ http://www.test.com/test1.html$1 [R=301,L]

    则访问www.test.net.cn或test.net.cn开头的域名会跳转到http://www.test.com/test.html,www.test.net或test.net开头的域名会跳转到http://www.test.com/test1.html。

    注意一些符号及参数:

    ^www.test.net.cn表示以www.test.net.cn为开头,和所有语言一样,!代表否,即!^www.test.net.cn表示不以www.test.net.cn开头。

    对mod_rewrite来说,!是个合法的模板前缀,表示“非”的意思,这对描述“不满足某种匹配条件”的情况非常方便,或用作最后一条默认规则。当使用!时,不能在模板中有分组的通配符,也不能做后向引用。


    R 强制外部重定向,后面可以代301或302跳转。


    L 表明当前规则是最后一条规则,停止分析以后规则的重写。(如果满足条件的话)


    OR 或的意思,上例中既是www.test.net.cn或test.net.cn开头的域名。


    NC 不区分大小写。


    $N 引用RewriteRule模板中匹配的相关字串。

    例如上例中的http://www.test.com/test.html$1,我个人测试的结果是:

    访问http://www.test.net.cn/132 会跳转到 http://www.test.com/test.html132

    这是个很有用的参数,如果去掉$1则无论http://www.test.net.cn开头的地址后面的链接是什么,最后都会转向:http://www.test.com/test.html


    重定向的缺点是域名无法保留,这一点是不推荐的,所以最好的方法还是对域名进行伪链接设置,写法也很简单,既去掉R=301,重写到当前服务器的相关地址路径即可:

    Options +FollowSymLinks
     
    RewriteCond %{HTTP_HOST} ^www.test.net.cn [NC,OR]
    RewriteCond %{HTTP_HOST} ^test.net.cn [NC]
    RewriteRule ^(.*)$ /test/cn/$1 [L]
     
    RewriteCond %{HTTP_HOST} ^www.test.net [NC,OR]
    RewriteCond %{HTTP_HOST} ^test.net [NC]
    RewriteRule ^(.*)$ /test/net/$1 [L]

    访问www.test.net.cn/** 就会跳转到对应的 localhot/test/cn/**,并且相关的域名www.test.net.cn仍会保留。

    附:RewriteRule 【参数详解】

    1) R 强制外部重定向,后面可以代301或302跳转。
    2) F 禁用URL,返回403HTTP状态码。
    3) G 强制URL为GONE,返回410HTTP状态码。
    4) P 强制使用代理转发。
    5) L 表明当前规则是最后一条规则,停止分析以后规则的重写。
    6) N 重新从第一条规则开始运行重写过程。
    7) C 与下一条规则关联。
    8) T=MIME-type(force MIME type) 强制MIME类型。
    9) NS 只用于不是内部子请求。
    10) NC 不区分大小写。
    11) QSA 追加请求字符串。
    12) NE 不在输出转义特殊字符。