当前页面位置: » 丰搜网 » 文档中心 » 详细内容
用xslt 和 xml改进struts
作者: julien mercay , gilbert bouzeid
原文:http://www.javaworld.com/javaworld/jw-02-2002/jw-0201-strutsxslt.html
译者: snake_hu(matrix id: dearhwj)
email:cleverhwj@163.com
msn:cleverhwj@163.com
摘要
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标志库加以修改让其输出x
html,这并不困难,但这就要修改现有的
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流的转换。为了提高性能xsl
servlet会对这个样式表进行了缓存处理。
xml流着由
struts的处理流程生成。你可以通过提供连续转化或者使用更高级的配置来改进这个简单的架构。cocoon中你就可以看到这两种方式的使用。cocoon
框架使用
xml和xslt构建
服务器端的应用程序。cocoon基于管道(pipeline)的架构使其能够更容易对内容和逻辑的加以分离、与大量不同的数据源交互也很方便。通过xslt,cocoon的输出可以与不同的设备兼容,比如
html、
wap等等。
图3显示的是xslt的处理流程。下面一节提供了一个将内容和版面设计分离的一个例子。
转化例子
testform是一个简单的窗体bean,它只有两个属性:
public class testform extends actionform {
private string teststring;
private list testlist;
}假设teststring的值为my test string,testlist的值为one、two、three,
xml串行化代码会生成一下
xml片断。在
xml文档中的元素名是可以预见的,这样编写样式表的时候会简单一些。
<page name="testform">
<request>
<testform>
<teststring>my test string</teststring>
<testlist>
<item>one</item>
<item>two</item>
<item>three</item>
</testlist>
</testform>
</request>
</page>
简单的xslt模板把已经串行化的
xml流转换到x
html片断。
<xsl:template match="page">
<h2>please enter some text and submit</h2>
<br/>
<form name="testform" method="get" action="result">
<input type="text" name="teststring"
value="{request/testform/teststring}"/>
<br/>
<select name="outselect">
<xsl:for-each select="request/testform/testlist/item">
<option><xsl:value-of select="."/></option>
</xsl:for-each>
</select>
<br/>
<input type="submit" value="submit"/>
</form>
<hr/>
</xsl:template>
经过转化和
html串行化,结果应该是如下
<h2>please enter some text and submit</h2>
<br>
<form name="testform" method="get" action="result">
<input type="text" name="teststring" value="my test string">
<br>
<select name="outselect">
<option>one</option>
<option>two</option>
<option>three</option>
</select>
<br>
<input type="submit" value="submit">
</form>
<hr>
model 2x主要的优势这一节我们讨论一下model 2x较之其他
模式的一些优势。
业务逻辑和表现逻辑的分离
xml文件流根据
模式(model)和上下文环境而生成,样式表对
xml文件流再进行加工。虽然一些xslt转换器可以支持一些扩展,通过这些扩展你可以在样式表中调用
java或是其他类型的语言。但这些扩展往往缺乏移植性,而且使用起来比较麻烦。这样就不能再把业务逻辑放入到xsl样式表。
标准技术的使用
xpath是一种强大的表达式语言,用来从
xml流中抽取出数据。我们可以通过使用<xsl:for-each>、<xsl:if>、<xsl:choose>这类的xslt元素配合上模板属性值,使用起来比
struts中的
html、logic、bean这些标签库好很多。xslt使用了w3c(world wide
web consortium)标准的语言,不但提供了和
struts标签库类似的功能,而且还有很大的提高。此外xslt还有一些标签库没有的强大功能,比如xslt支持函数和递归。
其他需要考虑的问题
这章中我们讨论在model2x中的如何实现国际化、错误处理、当前的一些限制以及以后可能的对model 2x的改进。
应用的国际化
本地化水平和目标语言的复杂程度会影响到了页面的布局,还有文本消息和图片。例如,阿拉伯文从右向左书写而旧式的中文从上到下书写。这些语言不但需要文本的翻译,同时还需要完全不同的页面布局。
struts开发人员通常把所有的文本信息和图像资源的链接根据不同的地区保存到一起。根据用户的地区,
struts就会调用适当的资源。
model 2x通过自动把资源存储到dom中,然后把他们传递给
视图。为了提高资源访问的效率可以对资源的读取和dom的建立缓存。model 2x 只是简单地把资源dom插入到最终的dom树中。这个最终的dom树也包括了从form bean生成的动态内容。你可以轻松地用xpath在xslt样式表中访问资源。应用的国际化不再通过
java资源捆绑技术实现,而是通过纯
xml技术——根据用户当前的地区动态地切换样式表来实现。
错误处理
验证错误通常指的是在
html表单中输入的参数出现的错误。通常我们把这类错误和其他类型的错误区分开来。验证错误以外的错误将被认为是较严重的错误。
在
struts中,可以在form bean中进行表单的验证,出现错误时会返回actionerror对象。把这些对象存储在请求中,然后串行化到dom树中。这样样式表就可以很容易地就把这些错误显示到窗体中。同样的,用户可以也可以在action中识别错误,然后把它们存储到请求中,进一步地串行化,最后用样式表来处理。
样式表会依据错误的类型和错误的内容选择是简单的显示一个错误的消息,还是将先前的页面重新显示,让用户修改数据后再提交。
工作流程
在这个model 2x架构中,
struts-config.
xml文件并不能像在原来的
struts架构中那样负责控制工作流程。不过,要说明的是这个问题实际上并不是model 2x的问题,而是这篇文章我们这个实现方案的问题。你可以在你自己的实现方案中修正这个问题。
输出
model 2x架构的一个重要的特性就是能够动态改变输出的内容类型以及用户接口的风格。比方说,同样的应用项目可以针对老版本的浏览器生成
html 3.2代码而同时又为新版本的浏览器生成
html 4.0的代码。利用xslt可以方便地获得各种输出格式: x
html、xsl/fo、wml、简单的文本、csv、pdf、svg等等。
xslt处理流程
model 2x标志着
web框架在分离版面设计与风格逻辑以及引导样式表这两方面有了提高。apache的cocoon
框架就表现出s了这两个优点。例如,某个样式表可以定义在整个站点中某类特定表格的显示样式,比如下面这张样式定义了用户信息表格的显示样式。这张样式表可能输出如下一个表格:
<xsl:template match="customer-info">
<table>
<tr>
<td>name</td>
<td><xsl:value-of select="name"/></td>
</tr>
</table>
</xsl:template>
而另一个样式表也可以通过创建一个如下的嵌入表来设计这个表格。
<xsl:template match="table">
<table cellpadding="0" cellspacing="0" border="0" bgcolor="red">
<tr>
<td valign="top">
<table cellpadding="4" cellspacing="1" border="0">
<xsl:apply-templates select="tr"/>
</table>
</td>
</tr>
</table>
</xsl:template>
<xsl:template match="@*node()">
<xsl:copy>
<xsl:apply-templates select="@*node()"/>
</xsl:copy>
</xsl:template>
性能
model 2x当前的这个实现方案是动态的创建
xml dom树,然后把它交给xslt转换器。通过使用sax(simple api for
xml)显著地提高了性能,特别表现在等待时间和大文档的内存驻留上。此外,样式表的编译也提升了xslt的处理次数。xalan是apache的一个xslt处理器项目。它提供了一种把样式表编译成
java的class文件的机制,也就是是我们所说的translets。
客户端处理
目前,ie5/6、mozilla这样的浏览器已经能够在客户端执行xslt转换。如果要减轻
web服务器的负担,可以在客户端执行xslt转换。xinclude(
xml inclusions)可以从
服务器下载资源和其他的数据,并建立缓存。xinclude提供了一种通用的方法来识别和处理它的内含物,同时还能够提供很好的性能、更少的代码冗余。当然这种方法也存在问题。最大的一个缺陷就是开发人员必须确保传递给客户的
xml、xslt文档必须是客户有权看到的内容。
通过model 2x来提升
struts的性能
总之,model 2x中使用
xml和xslt来鼓励开发人员将业务逻辑和表现逻辑加以分离,这样
web应用程序更接近mvc最基本的承诺。此外它还具有一些其它的优势比如输出的文档符合
xml的文档格式、标准化的语言的使用、更好的表现层适应性,更短的开发周期。
资源这篇文章附带的源代码:
http://www.
javaworld.com/
javaworld/jw-02-2002/
strutsxslt/jw-0201-
strutsxslt.zip