首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 软件管理 > 软件架构设计 >

Struts2最佳实践之一-在复杂实体对象中,怎么将页面参数转换为实体对象

2012-08-10 
Struts2最佳实践之一-在复杂实体对象中,如何将页面参数转换为实体对象Struts2是一个优秀的MVC框架,在很多

Struts2最佳实践之一-在复杂实体对象中,如何将页面参数转换为实体对象

Struts2是一个优秀的MVC框架,在很多项目中我都使用了它。因此希望能够记录一些自己在实践中总结的经验,以不断提高、并与志同道合的朋友一起讨论。

?

?

首先说明一下什么是复杂实体对象。一个实体对象,其所包含的属性不全都是简单数据类型(Long,String,Date等)时,就是复杂实体对象。如下图示:
Struts2最佳实践之一-在复杂实体对象中,怎么将页面参数转换为实体对象
?

?问题由来:一个相对复杂持久对象,某些属性关联其他实体对象。那么在编辑页面中,同时存在一般属性,以及关联实体属性。用户可以通过选择框等方式,改变关联关系。
简单举例:用户修改了自己的手机号,同时修改了自己的所属部门(用户是一个实体,部门是另一个实体)。那么我们保存时,怎么收集这些数据变化(包括根对象属性的改变,以及根对象到其他对象关联关系的改变)?
Struts2最佳实践之一-在复杂实体对象中,怎么将页面参数转换为实体对象
?场景抽象:在一个页面中,编辑的对象数据包含到其他对象的关联,即不全部是简单类型数据。如何设计Action接收用户输入的数据?方案1:在Action中定义一个根对象类型的成员变量,同时为所有相关联的实体对象的ID属性定义成员变量。如下图:在Action中,定义了根对象,也定义了关联对象的主键属性。

Struts2最佳实践之一-在复杂实体对象中,怎么将页面参数转换为实体对象
?
好处:结构简单。不足:定义的属性偏多;显得不那么OO(定义简单类型),没有充分利用参数的自动填充。

方案2:在Action中只定义一个根对象类型的成员变量,利用Struts的参数转换机制,将页面的平面数据,转换为有层次的对象数据。比如Action定义一个属性为entity,页面上的参数名称为entity.id、entity.name、entity.other_entity.id。Struts2最佳实践之一-在复杂实体对象中,怎么将页面参数转换为实体对象
?
好处:定义的属性少
不足:需要编码处理有可能为空的关联对象。

举个例子,我们正在编辑一个车辆的信息,车辆信息中包含驾驶员信息,驾驶员是系统里的另一个实体对象,那么我们在页面上可能就需要一个隐藏域来保存驾驶员id,并在页面上用另一个文本域来显示驾驶员名称,或者采用下拉框的方式。不过,当这个驾驶员信息可能为空的时候,【车辆.驾驶员.id】这个字段就为empty,但同样其会作为参数提交到服务端。那么Struts就会创建一个【车辆.驾驶员】对象,即使所有属性都没有值(原因是:提交的参数中,包含了该字段)。开始我认为是Struts参数处理的问题,为什么空值还要创建对象?于是写了一个Interceptor过滤所有值为空的参数,将其从参数列表中去掉(并不是从request中去掉,request中也无法去除)。后来才想明白完全是多此一举,本末倒置,甚至引入低级错误(如何客户想清空这个字段怎么办)。于是,又想,如果在页面上,通过脚本处理一下,将没有值的驾驶员ID域从FORM表单中去掉(DISABLE),这样就可以了吗?当然不行,还是那个问题,没有参数,STRUTS就不会自动SET参数值,也就没法将关联的驾驶员信息自动清空(SET成NULL),而是留下一个EMPTY的驾驶员对象(即其所有属性都为NULL)。最后,我认为,还是只有在服务器端,即Action中,手工将ID属性为空的关联对象设置为NULL,并将NULL设置给根对象,才能完美、正确的完成关联关系的改变。代码示意:
Struts2最佳实践之一-在复杂实体对象中,怎么将页面参数转换为实体对象
?乍看上去,好像这种代码有些奇怪。但是为什么在Action中处理是正确的?为什么在页面上无法处理?为什么参数自动填充无法解决这个问题?
首先,对于页面技术来说,当一个域被清空的时候,向服务器传递一个空值是唯一正确的方式。如果不传这个域,表明的意思应该是这个域没有变化,保持原状;其次,STRUTS的参数自动填充技术(包括相关对象的自动创建),不具有对象的概念。也就是说其不知道一个实体对象如果ID为空,那么这个对象也是没有意义的,也应该为NULL。STRUTS毕竟不是HIBERNATE。最后,既然STRUTS没有那么智能,那么只能由我们来代劳啦。

?

热点排行