结合struts和hibernate谈J2EE架构的数据表示

结合struts和hibernate谈J2EE架构的数据表示

在 struts+ hibernate 这种结构中,是不应该把Hibernate产生的PO直接传递给JSP的,不管他是Iterator,还是List,这是一个设计错误。

我来谈谈在J2EE架构中各层的数据表示方法:

Web层的数据表示是FormBean,数据来源于HTML Form POST
业务层的数据表示是VO
持久层的数据表示是PO,其数据来源于数据库,持久层的数据表示例如CMP

在一个规范的J2EE架构中,不同层的数据表示应该被限制在层内,而不应该扩散到其它层,这样可以降低层间的耦合性,提高J2EE架构整体的可维护性和可扩展性。比如说Web层的逻辑进行了修改,那么只需要修改FormBean的结构,而不需要触动业务层和持久层的代码修改。同样滴,当数据库表进行了小的调整,那么也只需要修改持久层数据表示,而不需要触动业务层代码和Web层代码。

不过由于Hibernate的强大功能,例如动态生成PO,PO的状态管理可以脱离Session,使得在应用了Hibernate的J2EE框架中,PO完全可以充当VO,因此我们下面把PO和VO合并,统称为PO。

先来谈谈ActionFormBean和持久层的PO之间的重大区别。

在简单的应用中,ActionFormBean和PO几乎是没有区别,所以很多人干脆就是用ActionFormBean来充当PO,于是ActionFormBean从JSP页面到Servlet控制层再到业务层,然后穿过持久层,最后一直映射到数据库表。真是一竿子捅到了底!

但是在复杂的应用中,ActionFormBean和PO是分离的,他们也不可能一样。ActionFormBean是和网页里面的Form表单一一对应的,Form里面有什么元素,Bean里面就有什么属性。而PO和数据库表对应,因此如果数据库表不修改,那么PO也不会修改,如果页面的流程和数据库表字段对应关系不一致,那么你又如何能够使用ActionFormBean来取代PO呢?

比如说吧,用户注册页面要求注册用户的基本信息,因此HTML Form里面包含了基本信息属性,于是你需要一个ActionFormBean来一一对应(注意:是一一对应),每个Bean属性对应一个文本框或者选择框什么的。

而用户这个持久对象呢?他的属性和ActionFormBean有什么明显不同呢?他会有一些ActionFormBean所没有的集合属性,比如说用户的权限属性,用户的组属性,用户的帖子等等。另外还有可能的是在ActionFormBean里面有3个属性,分别是用户的First Name, Middle Name, Last Name,而在我的User这个持久对象中就是一个 Name 对象属性。

假设我的注册页面原来只要你提供First Name,那么ActionFormBean就这一个属性,后来我要你提供全名,你要改ActionFormBean,加两个属性。但是这个时候PO是不应该修改滴,因为数据库没有改。

那么在一个完整的J2EE系统中应该如何进行合理的设计呢?

JSP(View) ---> ActionFormBean(Module) ---> Action(Control)

ActionFormBean是Web层的数据表示,它和HTML页面Form对应,只要Web页面的操作流程发生改变,它就要相应的进行修改,它不应该也不能被传递到业务层和持久层,否则一旦页面修改,会一直牵连到业务层和持久层的大面积的代码进行修改,对于软件的可维护性和可扩展性而言,是一个灾难,Actiont就是他的边界,到此为止!

Action(Web Control) ---> Business Bean ---> DAO ---> ORM --->DB

而PO则是业务层和持久层的数据表示,它在业务层和持久层之间进行流动,他不应该也不能被传递到Web层的View中去,而ActionServlet就是他的边界,到此为止!

然后来看一看整个架构的流程:

当用户通过浏览器访问网页,提交了一个页面。于是Action拿到了这个FormBean,他会把FormBean属性读出来,然后构造一个PO对象,再调用业务层的Bean类,完成了注册操作,重定向到成功页面。而业务层Bean收到这个PO对象之后,调用DAO接口方法,进行持久对象的持久化操作。

当用户查询某个会员的信息的时候,他用全名进行查询,于是Action得到一个UserNameFormBean包括了3个属性,分别是first name, middle name, last name,然后Action把UserNameFormBean的3个属性读出来,构造Name对象,再调用业务Bean,把Name对象传递给业务Bean,进行查询。

业务Bean取得Name(注意: Name对象只是User的一个属性)对象之后调用DAO接口,返回一个User的PO对象,注意这个User不同于在Web层使用的UserFormBean,他有很多集合属性滴。然后业务Bean把User对象返回给Action。

Action拿到User之后,把User的基本属性取出(集合属性如果不需要就免了),构造UserFormBean,然后把UserFormBean request.setAttribute(...),然后重定向到查询结果页面。

查询页面拿到request对象里面的ActionFormBean,自动调用tag显示之。

总结:

FormBean是Web层的数据表示,他不能被传递到业务层;PO是持久层的数据表示,在特定情况下,例如Hibernate中,他可以取代VO出现在业务层,但是不管PO还是VO都必须限制在业务层内使用,最多到达Web层的Control,绝不能被扩散到View去。

FormBean和PO之间的数据转化是在Action中进行滴。

BTW:

JDO1.x还不能像Hibernate功能这样强大,PO不能脱离持久层,所以必须在业务层使用VO,因此必须在业务层进行大量的VO和PO的转化操作,相对于Hibernate来说,编程比较烦琐。

当然咯,理论是一回事,实际操作也不一定非要这样干,你可以自行取舍,在实际项目中灵活一点,增加一点bad smell,提高开发效率。只不过在大型项目中最好还是严丝合缝,不然的话,改版的时候会痛苦的很滴。

 

转载于:https://www.cnblogs.com/encounter/archive/2007/10/27/2189238.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/380253.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

服务器appcrash的问题怎么修复,ghost win7出现appcrash的问题怎么修复

ghost win7出现appcrash的问题怎么修复一位用户说在win7旗舰版电脑中运行程序会出现appcrash错误的提示,appcrash出错想必很多用户都遇到过,也不知道什么原因引起的,导致程序无法正常运行。那么有什么方法可以解决ghost系统win7运行程序出现a…

远控免杀专题9 --- Avet免杀

0x01 免杀能力一查表 几点说明: 1、上表中标识 √ 说明相应杀毒软件未检测出病毒,也就是代表了Bypass。 2、为了更好的对比效果,大部分测试payload均使用msf的windows/meterperter/reverse_tcp模块生成。 3、由于本机测试时只是安装了360全…

字符串startswith_JavaScript字符串startsWith()方法与示例

字符串startswith字符串startsWith()方法 (String startsWith() Method) startsWith() method is a string method in JavaScript, it is used to check whether a string starts with a specified substring or not. startsWith()方法是JavaScript中的字符串方法,用…

方法:求两个数之和 判断两数是否相等

package wsq; import java.util.Scanner; public class wsq { public static void main(String[] args) { double a,b; Scanner wsqnew Scanner(System.in); awsq.nextDouble(); bwsq.nextDouble(); double cadd(a,b); System.out.println(“两数之和为:”…

WF随笔系列之三 --- Code Activity 专题

系列目录:WF随笔系列之三 Out-of-the-Box Activities 专题目录 Code Activity是WF开发中使用最频繁的Activity之一,它要做工作的很简单,就是把一个或者几个Code Exec 一下,当此行为在执行时,触发一个Handlers:Execute…

是知当代之士、驰骛之曹,书读纵横,则思诸侯之变

看到《职来职往》的智联招聘张勇为应聘者设计的一个问题,很有深度,值得借鉴: 是知当代之士、驰骛之曹,书读纵横,则思诸侯之变; 出自原文: 匠成舆者,忧人不贵; 作箭者&…

A5流密码算法

0x01 A5/1流密码算法的基本用法 作用: 用于蜂窝式移动电话系统语言和数字加密 过程: A5/1算法用于用户的手机到基站之间的通信加密,通信内容到基站后先解密变成明文,然后再进行基站到基站之间,以及基站到用户手机之间…

mcq 队列_MCQ | 密码学中作为IDEA,DES,AES,RSA的块密码

mcq 队列1) In the AES-128 algorithm there are mainly __________ similar rounds and _________ round is different from other round. 1)在AES-128算法中,主要有__________个相似的回合,而_________个回合与其他回合不同。 5 similar rounds havin…

Cookie存取和IE页面缓存的问题

最近老是发现在IE里会有Cookie的问题,如IE下面无法登出,或无法登录,或者登录后信息却无法取到,而Firefox下面一直是通过的,都试过好多次了,今天终于找回的主要的原因;Cookie的问题:首…

数组(一维、二维)

1, 动态初始化: int [] arr new int [5] 如果直接输出arr; System.out.print(arr); 结果为: [I13b64eb [:表示一维数组,几个就代表几维数组; I:表…

Extjs TextField扩展

Extjs.form.TextField的默认在输入框后面是不能加入文字。在网上找到此方法以备查用。 /** * 重写textfield,为其多加一个属性sideText,在文本框后面加html * author rms * create 2011-08-17*/Ext.override(Ext.form.TextField, { sideText : , onRender : functi…

远控免杀专题10--TheFatRat免杀

0x01 免杀能力一览表 几点说明: 1、上表中标识 √ 说明相应杀毒软件未检测出病毒,也就是代表了Bypass。 2、为了更好的对比效果,大部分测试payload均使用msf的windows/meterperter/reverse_tcp模块生成。 3、由于本机测试时只是安装了360全…

c++语句switch语句_错误:案例标签不在C中的switch语句内

c语句switch语句The error: case label not within a switch statement occurs in C language with switch case statement, when switch (variable/value) statement is terminated by the semicolon (;). 错误:当switch(变量/值)语句由分号( ; )终止时&#xff0c…

远控免杀专题11-Avoidz免杀

0x01 免杀能力一查表 几点说明: 1、上表中标识 √ 说明相应杀毒软件未检测出病毒,也就是代表了Bypass。 2、为了更好的对比效果,大部分测试payload均使用msf的windows/meterperter/reverse_tcp模块生成。 3、由于本机测试时只是安装了360全…

使用方法实现数组的对调与输出

package asdasqq; import java.util.*; public class asdasdad { public static void main(String[] args) { Scanner wsqnew Scanner(System.in); int qwsq.nextInt();//输入q,表示数组arr的大小; int [] arrnew int [q];//定义一个整型数组arr&a…

CAP与流密码

CAP 中流密码的操作 1 、Cipher 下拉菜单中选中Stream 2,设置LFSR 参数,设置好参数后点击Set Key LFSR Size:表示有几个寄存器 Initial key:寄存器的初始状态,每个寄存器初始值是0或1,放在一起转化成十六进制 Feedbac…

高性能Javascript 用局部变量缓存集合元素

document.images; 由于集合元素是处于实时状态的实时存在,它与底层dom连接着。在遍历它的每一个属性或length时都会带来查找,从而性能开销很高。 这里是有关集合元素在循环处理时的优化原则 一、用变量缓存集合元素 二、在循环在缓存集合length属性 三、在循环中用变…

QTP中使用描述性编程

我们简单介绍一下有关功能测试的基本方法,这实际上对于所有自动化功能测试产品来说都是一样的。一般情况下,用QTP来进行功能测试的基本方法主要包括三个主要阶段: 1、创建测试或组建 首先可以通过在应用程序或网站上录制会话,或…

字符数组的查找法

package asdasqq; import java.util.*; public class suoying { public static void main(String[] args) { Scanner wsqnew Scanner(System.in); System.out.print(“请输入对应的星期范围在一~日:”); int week wsq.nextInt(); System.out.print(getWeek(…

结构和其他数据形式

0x01 结构声明 结构声明(structure declaration)描述了一个结构的组织布局。 struct book{char title[MAXTITL];char author[MAXAUTL];float value; };该声明描述了一个由两个字符数组和一个float类型变量组成的结构。该声明并未创建实际的数据对象&am…