DWR帮助说明-如何编写通用的列表显示框

  也许朋友们会以为这是 DWR 官方 发布的什么帮助,但非常遗憾这不是。现在不少朋友在使用 DWR 开发项目,我也是其中之一,但苦于关于 DWR 的帮助文档实在太少,很多问题都不得不自己去钻研 DWR 的源码才能解决或理解。经过一段时间的苦苦钻研,总结出那么一点点心得,现在从 DWR 源码实现的角度详细讲解 DWR 的使用,写出来与大家分享。今天我谈一谈如何编写通用的页面端 DWR 代码。

看了DWR官方发布的示例代码,朋友们可以发现,在该示例代码中,每一个功能都至少有一个jsp文件和一个js文件。也就是说,示例中的每一个功能都需要我们为该功能单独地编写javascript代码,而没有能够有效的代码复用,这是我们不愿意看到的。然而,这仅仅是DWR提供给我们的示例代码,它可以不用过多考虑一些技术细节,但我们使用DWR开发项目则不得不考虑。那么,我们如何在使用DWR的过程中尽可能地代码复用呢?我想,我们先梳理一下页面端的DWR代码如何编写,然后一步一步分析总结这些代码应当如何复用,思路会更加清晰一些。

一、列表显示功能

首先,我们先看一看DWR的列表显示功能。DWR示例中的people目录中展示了一个列表显示功能。总结一下示例中的列表显示代码大致有这几个步骤:

1、调用一个服务器端某个对象中的一个查询方法,如DepartmentBus.findDepartment();这里的DepartmentBus和它的方法findDepartment()对应的是服务器端的一个类及其方法,并已经在dwr.xml中注册了的。在这里调用该方法看起来好像与在java中调用比较相似,但有一个很大的区别就是它的返回值。在java中获得返回值是将某个变量等于该函数:

List rs = DepartmentBus.findDepartment(String hql);

但在js中使用DWR应当这样写:

DepartmentBus.findDepartment(String hql, function(resultset){ … });

在这段代码中,function(resultset){ … }中的resultset变量就是返回值,而这个function中的内容就是对返回值的处理过程。在javascript中,一个function也被当作变量看待,只是一个可以调用的特殊变量。因此你也可以将以上代码写为这样:

DepartmentBus.findDepartment(String hql, getResultset);

function getResultset(resultset){ … };

甚至可以将后面这个函数写成这样:

getResultset = function(resultset){ … };

这样的代码比较奇怪是吧,习惯了就不奇怪了。

2 、现在应当来实现 getResultset 中打省略号的部分,示例中是使用一个 DWR 的函数 removeAllRows 来删除 table 中所有的行,除了那个作为模板的行,其 id 取名为 pattern 。这个名为 pattern 的行十分重要,它被设置为不显示,但表格中的其它行都是由这一行进行克隆得到的。

3、执行一个循环语句,从resultset中依次取出值对象,然后使用DWR的函数cloneNode使用模板行克隆一个新行,然后使用数个DWR的函数setValue将值对象中的属性设置到这个新行的对应列中。当然,这个新行的各个列的id应当设置成属性名加列号。比如在设置第三行时,应当将该行的“部门编号”列的id设置为“departmentId002”,并在向该列赋值的时候写为:setValue(‘departmentId002’, vo.departmentId);其中vo就是这个值对象。另外,在完成对该行的赋值操作以后,为了今后的执行效率考虑,将一个叫objCache的变量作为页面的结果集缓存,将该行的值对象放进这个数组变量中。

经过这样三个步骤,DWR就实现了从后台查询出数据集并写入到页面的表格中。但这样一个过程我们可不可以写一个通用的代码,使得各种不同表的不同数据都可以通过少量程序就可以完成了?但不幸地是,以上的代码不能直接抽象出一个通用代码,我们必须需要进行改造。问题出在第三个步骤的setValue()函数。按照示例的思路,对于Department应当这样写:

setValue(‘departmentId002’, vo.departmentId);

setValue(‘departmentName002’, vo.departmentName);

而对于另一个表格Employee应当这样写:

setValue(‘emplyeeId002’, vo.employeeId);

setValue(‘name002’, vo.name);

setValue(‘sex002’, vo.sex);

也就是说,我们不得不根据值对象的不同分别去写setValue语句而不是一个通用语句。但所幸的是,DWR还提供另一个函数setValues(),你只需要将值对象传给它,它将把id等于属性名的对象设置为该属性的值,比如有个id等于departmentId的text框就会被setValues()设置成显示departmentId对应的值。然而这里使用setValues()有一个问题,值对象中只有departmentId属性,而在表格中我们为了区别不同的行,将每行的“部门编号”标签的id设置为departmentId000、departmentId001、departmentId002……与属性名不一致了。怎么办呢?如果我们把setValues()进行一些改造,使其能够提供后缀的功能就迎刃而解了,即将后面的序号作为后缀,以参数的形式传给setValues(),这样一个通用的列表查询函数就写出来了。具体的做法是我重新实现了DWR的setValues()和_getDataProperties()并提供了3个将结果集填充到表格的函数fillTable()fillResult()fillTableWithCache()fillTable()用于直接将结果集填充到表格中,fillResult()将表格填充的同时还实现了无刷新页面翻页的功能,而fillTableWithCache()则用于当数据更新时不查询后台而直接通过页面的结果集缓存变量刷新数据。具体的实现见我提供的示例。

二、前缀

前面我提到了后缀的功能,即页面在列表显示的时候,为了使表格中的数据既可以与值对象的属性对应,又可以使各列之间的id名称有所区别,在将标签的id名称设置为“属性名+行号”,这个行号就是后缀。然而DWR还提供了前缀的功能,这又是什么意思呢?

DWR一个非常重要的特点是将页面的id与后台值对象的属性名对应起来。通过这样,过去我们在MVC需要做的非常烦杂的,将页面的form中一个一个取出数据,再一个一个放到值对象的工作,变成了一个简单的setValues()的操作。但是这样却带来了另一个问题:同一个表的数据在一个页面中需要在多个部分显示,就会出现多个标签使用同一个id形成冲突的问题。比如,一个非常普遍的应用,在一个页面中同时包含一个列表显示框和一个单行编辑框。当用户选择列表显示框中的某行并点击“编辑”按钮,该行的信息将显示在单行编辑框中进行编辑,编辑结束并保存后将更新该行到列表显示框中。在列表显示框中如果显示的是所有部门的信息时,虽然各行标签的id取名为“属性名+行号”,但列表框中那个用于克隆的模板行却是取名为值对象的属性名,如departmentId、departmentName等。而在该页面中的单行编辑框中显示的也是部门信息,因此取名也是部门值对象的属性名。这样,在这个页面中将有两个id为departmentId的标签,两个id为departmentName的标签,id出现了冲突。众所周知,在一个页面中id应当是唯一的,如果出现id冲突将出现错误。解决这个问题的办法当然就是使用前缀。

如果在设计页面的时候出现id冲突,我们可以在id前添加一个前缀,如在departmentId前添加一个tbody,写成tbody. departmentId,而另一个添加另外的前缀,id冲突的问题就解决了。对于添加了前缀的标签,在调用setValues()和getValues()函数的时候应当将前缀作为参数传递过去,写法如下:

setValues(department, { prefix:tbodyid, postfix:id });

后面的后缀就是我重写setValues后提供的功能。

示例:一个dwr+spring+hibernate的示例

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值