本文共 5034 字,大约阅读时间需要 16 分钟。
本文主要描述的是如何通过Data Transfer Object (DTO)来实现EJB Container和Web Container之间的数据传递,以及如何将Web Container获得的数据(DTO)用经过扩展Cocoon在Web页面上进行显示,并通过具体的实例介绍作者在开发过程中遇到的实际问题的解决方 法。
本文描述的系统在开发时采用JBoss作为应用服务器,Web端开发采用Struts + Cocoon实现Model 2x的设计模式。
本文是作者在实际项目中的一些感受,在给广大同行一些可能存在的启发的同时,希望能够听到其他的声音。下图是本文要描述的整体框架。
![]() ![]() |
![]()
|
![]() ![]() |
![]()
|
Model 1
Model 1的基础是JSP文件,它由一些相互独立的JSP文件,和其他一些Java Class组成(不是必须的)。这些JSP从HTTP Request中获得所需要的数据,处理业务逻辑,然后将结果通过Response返回前端浏览器。Model 1的应该说是唯一的好处是"简单",可以大大加快系统的开发进度。它把表现层和业务逻辑层柔和在一起,不利于以后的维护工作以及开发角色的分配,所以这种模式只能适合于小的系统开发。
Model 2
采用面向对象技术实现MVC模式从而扩展JSP/Servlet的模式被成为是Model 2模式。Apache Jakarta项目中Struts是一个实现Model 2的很好的框架,它通过一些Custom Tag Lib处理表现层,用ActionFrom Bean表示数据,用自己提供的一个ActionServlet作为控制器实现页面的流转的控制功能。如下图:解释如下:
Struts强制开发人员采用MVC的设计进行系统开发,虽然它会带来如将表现层和业务层分开,合理安排开发人员角色等诸多方面的好处,但也存在一些缺点:
Model 2x
将Struts中的View层用XML/XSLT技术替换掉,这就是我们要提到的Model 2x模式。Apache Cocoon是Jakarta项目组提供的另外一套XML技术框架,配合Struts一起使用,将很好的解决我们上面遇到的这些问题。那么现在的结构如下 图所示。这样的结构会带来如下一些优点:
但是,任何一种架构或者解决方案都是双刃剑,在我们获得的同时必须有一定的付出。这种模式也带来了如下一些实际的问题。
这些问题我们会在简单介绍DTO/DTO Factory模式之后,综合EJB容器和Web容器之间的数据交换的基础上用具体的例子来描述。
![]() ![]() |
![]()
|
这里我们不会涉及在EJB系统开发时的这两种模式的详细情况,详细情况请参见"资源"部分。
Data Transfer Object(DTO)模式是为了解决这样的问题:例如我们的一个实体Bean,其对应的数据库表的字段非常多,那么我们在其Home接口的create 方法中以及Enterprise Bean类的ejbCreate方法中的参数可能就会很多,导致我们的这些方法不够elegant。我们可以通过定义一个简单的Java类(实现 Serializable接口),其中定义一些属性,并提供相应的get和set方法来解决上面的问题。
DTO又分成是 Domain DTO(它对应于数据层的某一个实体Bean)和用户自定义的DTO(用户为了满足自己个性化的数据需求,比如多表查询)。那么当系统有一定规模的时候, 这些DTO就会很多,于是引进了DTO Factory模式,从而使得EJB的客户在访问这些数据的时候有一个统一的接口。
![]() ![]() |
![]()
|
前面我们提到了一些关于Model 2x的问题,在这里我们通过实际的例子来解决。
1. 首先我们需要定义数据结构,来解决诸如用户列表和XML/XSLT报表的问题。在以往的项目我们经常使用如下一种XML结构:
Value1 Value2 … … |
该结构的特点是其中包含一些属性以及一个列表。
2. 对于这样的数据结构,我们定义如下的一个DTO类来表示,并扩展了上面的结构中只包含一个列表的情况。
public class CommonDTO implements Serializable { //定义一个LinkedHashMap用来保存DTO中的各个属性值;同时采用LinkedHashMap //的原因在于我们可能需要其中各个属性的顺序,比如在页面显示一个用户列表的时候, //我们希望第一列是ID,第二列是Name等 private LinkedHashMap attributes = new LinkedHashMap(); //用一个列表存储该DTO可能包含的其他DTO。列表中的每个元素仍然是DTO private ArrayList childDTOs = new ArrayList(); public void addChildDTO(CommonDTO child) { … } public Iterator getAttributeKeys() { … } public Iterator getAttributeValues() { … } public void setAttribute() { … } } |
从上面的例子中可以看出,我们现在的DTO已经不在包含一个线性结构的列表,而是一个树状结构。它除了可以满足1中提到的数据结构外,还做了进一步的扩展。
3. 扩展Cocoon
对于Struts通过Business Delegate从EJB Container中获得一个DTO,如何交给Cocoon的Pipeline(管道),最终生成HTML呢?我们需要扩展一个自己的Generator。
public class RequestCommonDTOGenerator extends AbstractGenerator { CommonDTO dto = null; public void generate() throws java.io.IOException, org.xml.sax.SAXException, org.apache.cocoon.ProcessingException { AttributesImpl emptyAttr = new AttributesImpl(); contentHandler.startDocument(); contentHandler.startElement("", "DTO", "DTO", emptyAttr); //Root Element Starts //Process the DTO object CommonDTOSAXHandler.transferCommonDTO2SAX(dto,contentHandler); contentHandler.endElement("", "DTO", "DTO"); //Root Element Ends contentHandler.endDocument(); } … } |
我们自定义的这个类从 org.apache.cocoon.generation.AbstractGenerator中继承,重载父类中的generate方法,通过SAX 将DTO转化成XML,交给Cocoon管道(Pipeline)中的后续工序加工。其中的CommonDTOSAXHandler是我们自己定义的另外 一个类,它利用其中的静态方法tranferCommonDTO2SAX,递归处理我们的DTO。
对于这样的方案,有以下一些需要说明:
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/374079/viewspace-130513/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/374079/viewspace-130513/