ITPub博客

首页 > Linux操作系统 > Linux操作系统 > [转载]Model 2x的Web应用和EJB Container的数据传递

[转载]Model 2x的Web应用和EJB Container的数据传递

原创 Linux操作系统 作者:dinner1007 时间:2019-05-25 17:48:06 0 删除 编辑

Model 2x的Web应用和EJB Container的数据传递


本文主要描述的是如何通过Data Transfer Object (DTO)来实现EJB Container和Web Container之间的数据传递,以及如何将Web Container获得的数据(DTO)用经过扩展Cocoon在Web页面上进行显示,并通过具体的实例介绍作者在开发过程中遇到的实际问题的解决方 法。

摘要

本文描述的系统在开发时采用JBoss作为应用服务器,Web端开发采用Struts + Cocoon实现Model 2x的设计模式。

本文是作者在实际项目中的一些感受,在给广大同行一些可能存在的启发的同时,希望能够听到其他的声音。下图是本文要描述的整体框架。






回页首


内容提要

  • Model 1, Model 2和Model 2x的介绍
  • DTO/DTO Factory设计模式的介绍
  • 扩展Cocoon,解决实际项目中遇到的问题
  • 资源



回页首


Model 1, Model 2和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作为控制器实现页面的流转的控制功能。如下图:



解释如下:

  1. ActionServlet是Struts提供的一个Servlet,它在Web应用启动的时候被启动。所有的HTTP请求全部经过这个控制器,然后由它转发给模块;
  2. Struts负责将附着在Request上的参数组装成ActionForm bean;
  3. 然后将ActionForm bean传给某个具体的Action类进行处理;
  4. 将处理的结果保存在一个bean中;
  5. 通过Struts提供的Custom Tag Lib将结果bean中的信息显示成HTML发送给浏览器。

Struts强制开发人员采用MVC的设计进行系统开发,虽然它会带来如将表现层和业务层分开,合理安排开发人员角色等诸多方面的好处,但也存在一些缺点:

  1. 由于View层采用JSP,所以开发人员还是可以在其中写上一大堆的Java代码,从而使最后的系统还处于一种混乱的状态。而实际上开发人员确实会出现这种状况;
  2. 开发人员需要学习Struts提供的Custome Tag Lib,这需要时间,尤其对以前只熟悉HTML的页面设计人员来说,同时其中的一些Tag已经被Java Standard Tag Library取代掉了。

Model 2x
将Struts中的View层用XML/XSLT技术替换掉,这就是我们要提到的Model 2x模式。Apache Cocoon是Jakarta项目组提供的另外一套XML技术框架,配合Struts一起使用,将很好的解决我们上面遇到的这些问题。那么现在的结构如下 图所示。



这样的结构会带来如下一些优点:

  1. 避免了开发人员将逻辑代码直接写在JSP中,从而明晰地划分了业务逻辑层和表现层的界限。后台的Java程序员只需要关心业务逻辑的实现,最后将结果用XML来表示;而页面设计人员只需要关心如何美化页面,只要双方定义好中间的数据接口;
  2. 借 助XSLT,开发人员可以完全不用学习Struts提供的那些已经不标准的Custom Tag。这个问题我们可以从输入页面和输出页面来考虑。对于输入,不管我们的JSP页面(对于Struts来说)采用什么样的技术,最终在浏览器中显示的 始终是HTML,那么我们完全可以不用Struts提供的例如html:form等Tag,而是直接用HTML来描述,只要我们注意表单(form)中的 字段和ActionForm中属性之间的对应关系即可;而对于输出页面来讲,借助XSL/XSLT的帮助,我们也完全可以抛开Struts的Tag,将 XML最终显示成HTML。
  3. 从上图中我们可以看到,对于Struts部分在结构上没有任何变化,只是另外加了一个 层次。而对于Cocoon来说,虽然看上去我们又多用了一个框架结构,但实际我们不需要对Cocoon做什么程序编写工作,只是需要多维护一个 sitemsp.xmap文件(一个XML文件)。

但是,任何一种架构或者解决方案都是双刃剑,在我们获得的同时必须有一定的付出。这种模式也带来了如下一些实际的问题。

  1. 开发人员需要学习XSL。但我们毕竟需要学习一些东西,相信XSL中对逻辑以及对数据格式等诸多的方便处理给我们的开发人员的项目经理一些学习这些东西的理由;
  2. 如何定义我们的数据结构,从而满足我们的业务需求。在自己做过的项目中,经常会遇到一些返回例如用户列表,用XML/XSLT显示报表的具体问题,那么如何能够定义一个比较好的数据结构方便地处理类似的问题呢?
  3. 如 何使用Cocoon的Pipeline将我们的数据结构转化成XML并最终显示成HTML?经过研究发现,Cocoon提供的Generator无法满足 我们具体的数据处理的要求。这个问题我们可以通过扩展Cocoon的Generator来解决。后面我们会提供一个示例。

这些问题我们会在简单介绍DTO/DTO Factory模式之后,综合EJB容器和Web容器之间的数据交换的基础上用具体的例子来描述。




回页首


EJB开发中的DTO/DTO Factory模式的简单介绍

这里我们不会涉及在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的客户在访问这些数据的时候有一个统一的接口。




回页首


扩展Cocoon,用解决实际项目的问题

前面我们提到了一些关于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。

对于这样的方案,有以下一些需要说明:

  1. 这样做的好处是避免了维护过多DTO,从而是EJB Container和Web Container之间的数据传递有了一个统一的接口;
  2. 完全有可能使开发人员不再学习Struts中的Custom Tag,甚至可以不使用JSP;
  3. 在开发的过程中,需要注意从HTML的表单(form),到ActionForm bean,到Entity Bean,这些元素中的属性的命名一要规范,二要统一。
  4. 借助Java Reflect的使用,可以避免在封装DTO时可能过多出现在代码中出现hard code的可能(例如,我们需要用dto.setAttribute("username","Charles")来设置DTO中的某个属性)。

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/374079/viewspace-130513/,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2018-08-23

  • 博文量
    1467
  • 访问量
    1085842