摘要
Struts是一个优秀的java Web开发框架。Struts是Apache项目之一,现在Struts已经在Java开发团体中得到了广泛的支持。在这篇文章中Julien Mercay 和Gilbert Bouzeid将向我们介绍Struts的处理流程、描绘Struts框架,最后提出了Model 2x。Model 2x用xml/XSLT替换掉了原来的表现层中的jsp页面。Model 2x通过这种方式更加明晰地划分了业务逻辑层和表现层。
正文
自从Servlet API发布以来,Java开发人员使用了不同的技术来开发Web应用程序。Web开发人员已经熟悉到了Model 2的优点。Model 2 指的是基于MVC模式的WEB开发框架。Model 2能把应用逻辑层和表现层较好地区分开来。Struts构建在Model 2 之上,它向Java开发人员提供了一个普通的控制器Servlet,还有集中式的资源配置、资源治理以及错误处理等功能。
这篇文章中我们引入了Model 2x。Model 2x可以将逻辑层和表现层更好地分离。我们先介绍Model 1和Model 2,然后讲述一下Struts是如何实现MVC架构的,最后向读者展示一下如何通过XML、XSLT来对现存的模式加以改进。
Model 1
理解Model 1是十分重要的,假如不熟悉Model 1将很难理解我们在文章中介绍的其他几个架构。Model 1的基础是JSP文件。JSP从Http请求中取得参数,调用所需的业务逻辑,处理Http对话,然后生成Html页面。
一个完整的Model 1项目包括一组JSP文件(这些文件大部分都是彼此独立的)、一组所需的Java类和其他组件。一些早期的Web开发技术比如asp、php都使用类似的模式来开发的。
Model 1主要也许是唯一的优势就是简单。Model 1中业务逻辑和显示逻辑混合在JSP页面中没有进行抽象和分离,所以在进行快速和小规模的应用开发时,有非常大的优势的。但用Model 1 开发复杂的项目的开发时,将不可避免地导致项目治理的困难。
Model 2, MVC, and Struts/JSP
图1
图1说明的是MVC架构中的三个部分,以及它们在Struts/JSP中的实现。
控制器(Controller):Struts的最主要的部件就是一个普通的控制器Servlet。控制器是每一个发送到Struts的Http请求的入口点。控制器把所有的请求经解释后分发action。这些action是Struts Action类的子类。由开发人员负责实现它们。控制器也会自动的把Http请求中的参数加入到Form bean中。Action负责实现核心的业务逻辑,比如做EJB调用,通过Java Bean访问模型(model)。在Struts中可以通过定义一个XML文件来描述请求URI、具体业务逻辑处理、代表客户提供的数据的Form组件三者之间的映射关系。控制器的就是通过这个XML文件来定义的。
模型(Model):
Java beans就是模型的代表。这些bean分成3类:
窗体Bean(Form Bean)对象用来包装HTML表单数据,当然也包括通过URL请求传递过来的数据。举例来说,一个登陆页面可能有两个属性(PRoperty)login和passWord。Form Bean由Struts的ActionForm类扩展而来。
请求Bean(Request Bean)拥有用来生成HTML页面的所需的信息。例如在一个表现银行账户状态的页面中,请求Bean就应该有账户相关信息以及近期的交易记录等等。
会话Bean(session Bean)拥有同一用户在不同Http请求间共享的对话信息。
视图(View):
Struts控制器会把Http请求转发到作为MVC视图的JSP文件。这个JSP文件可以访问窗体Bean、请求Bean、会话Bean,生成结果文档(通常是一个HTML文档),并发送到客户端。Struts提供了四组JSP标志库。
HTML:用来生成HTML标志,非凡是用来自模型的数据填写HTML表单。
Bean: 操作Bean。
Logic: 根据Bean值实现逻辑结构。
Template:处理页面模板。
通过Struts标志的使用,你可以避免在视图中使用任何的Java代码。
Struts/JSP 缺点
虽然Struts/JSP较之其他模式有许多优势,但它也存在着一些缺点和不足:
程序员可以把应用逻辑放入JSP。碰到问题时,开发人员可以很快地加以修改,经验表明这实际上是陷阱。程序结构很轻易变得复杂和难于治理。
JSP不能很好地支持XML,也就不能保证生成的结果文档(XML或HTML文档)将会是100%“格式良好”(Well-Formed)。
开发人员需要学习如何使用Struts的标志库。事实上要理解这些Struts的标志库,非凡是Bean和HTML标志库的确要花费比较长的时间。
你不能在视图中用JSP来实现处理管道(processing pipeline)。只能做些简单的include和forward,这样很明显就会限制了视图的灵活性。例如,对布局计和风格的分离就会比较困难。
对JSP页面的任何修改都会导致JSP的重新编译,这样是非常耗费时间的。
上述问题的解决方法必须要具备以下要求:
限制视图对模式和一些定义明确的上下文环境信息的可见程度,比如项目资源的可见程度就应该受到控制。
强制使用格式良好的XML和HTML
能够对在现存的语言或API起到杠杆作用
降低对视图不同部分分离的难度,比如布局和风格的分离。
缩短开发周期
我们相信我们接下来讨论的这个基于未加修改的Struts和XSLT的轻型框架可以满足上述的要求。我们把这个新的架构叫做Model 2x
Model 2x架构概观
Model 2x是 Struts和XSLT结合的产物。Model 2x基在视图部分用XSLT和最后会被串行化成XML文件的Bean替代了原来Struts视图部分的JSP文件,但原封不动地保留Struts的Controller和Model部分。
XSLT定义
作为一种W3C的正式标准,XSLT是用来对XML文档进行转化的一种语言。它是XSL(可扩展样式表语言)的一部分。XPath是用作对XML文档各部分进行定位的语言。在XSL样式中,我们可以利用XPath表达式以一种紧凑而高效的形式选取XML文档的一部分进行处理。
XSL/FO也是XSL的规范的一部分,用来描述显示给读者的页面外观。XSL/FO主要的一个应用就是生成PDF文档。
XSLT和Struts的合成
把Struts和XSLT结合在一起的方法一是在JSP页面中执行XSLT转换。我们可以用标志库来实现这一功能,比如你可以使用Jakarta项目中的一个XSL标志库项目来实现。假如使用这种方式,那么在JSP页面中生成的是应该是XML而不是原来的HTML。借助XSLT样式表,XML转化成HTML或其他格式。然而这种方式需要对Struts本身加以修改。
生成HTML最通常的方式是由Struts的HTML标签库来生成,但这类标志库与XML并不兼容,也就不能和XSLT结合起来使用。当然可以对HTML标志库加以修改让其输出XHTML,这并不困难,但这就要修改现有的Struts 1.0 代码。
此外,这一解决方案需要在四个不同的地方开发:Action 类(控制器)、模型Bean、JSP页面、XSLT样式表(视图)。JSP与标签库的作用也只限于把模式Bean转化成一个XML文档。
第二种方法就是我们提出的Model 2x。这种方法会自动执行这一任务,而且把JSP页面从我们的解决方案中删除了。图2向我们很好地展示了Model 2x设计的核心构成。
图2
我们从图2中可以看出来,Model 2x处理流程的最初部分和Struts的类似。请求被发送到Struts的控制器,然后又被分派给各自的业务逻辑处理单元(Action类的子类)。控制器创建ActionForm对象。请求的参数都保存到这个ActionForm对象中。Action类的子类生成结果Bean(Result Bean),然后把这些Bean交给视图来显示。
Model 2x和Struts处理流程不同的地方在于:Model 2x中用一个XSL Servlet配合XSLT样式表实现了原来在Struts中由JSP实现的视图部分。这个XSL Servlet首先根据Bean和上下文环境生成XML文档,然后调用XSLT进行转换。接下来我们会具体地讲述这个过程。由于我们可以把一个请求提交给任何一个已经在Struts配置文件中注册的URL,所以在这个过程中不用对Struts做任何的修改。
XML文档的生成
把一个对象转换到一个Stream的过程我们称之为串行化。在Java 1.1中引入了java.io.Serializable接口和相关的API。二进制串行化可以把一个Java对象转化到二进制流,在网络上传输或是保存到文件中。相比之下,XML串行化是把一个Java对象树转化到文本型的XML流中。
许多开放源代码的软件包,譬如Castor都可以用来执行XML串行化。在我们文章中提到的Model 2x案例中我们自行设计了一个简单的XML串行化方案。这个方案中假设Bean的所有属性是Java的基本类型或者java.util.Colleciton的子类。
这个方案会递归地对窗体Bean(Form Bean)、请求Bean(Request Bean)和Session bean进行自省,创建一个DOM树。同时,也串行化了资源和Struts配置数据也就是上下文环境信息。图3说明了这个过程
图3 XML/XSL 工作流程
XSLT处理
在这个Model 2x案例中,XSLT转换只限于样式表对XML流的转换。为了提高性能XSLServlet会对这个样式表进行了缓存处理。XML流着由Struts的处理流程生成。你可以通过提供连续转化或者使用更高级的配置来改进这个简单的架构。Cocoon中你就可以看到这两种方式的使用。Cocoon框架使用XML和XSLT构建服务器端的应用程序。Cocoon基于管道(Pipeline)的架构使其能够更轻易对内容和逻辑的加以分离、与大量不同的数据源交互也很方便。通过XSLT,Cocoon的输出可以与不同的设备兼容,比如HTML、WAP等等。
图3显示的是XSLT的处理流程。下面