将视图组合在一起以便于构造 web 应用程序
级别:中级
wellie chao(wchao@caraveltech.com)
总裁,caravel technologies
2002 年 8 月
“模型-视图-控制器(model-view-controller,mvc)”框架对于生成有组织的模块化应用程序(这些应用程序能够清晰地划分逻辑、样式和数据),是一种经证实的和方便的方法。在 java 世界中,struts 是最著名的也是最常被谈及的 mvc 的开放源码体现之一。致力于 struts 的开发人员最近增强了该项目的核心功能,并改进了视图支持(合并了 tiles 视图组件框架来加强对基于组件开发的支持),以便增加可重用性并增强一致性。本文中,wellie chao 说明了 struts 和 tiles 组合为什么是用来创建 web 应用程序的最佳工具包,而且向您展示了如何开始使用它,这里主要讲述自 struts 0.9 以来的更改。
我开始学习如何创建软件要追溯到 80 年代中期,最初两个月的时间都花在使用线性流及嵌入式显示、逻辑和数据编写单块代码。这在那时,好象是最常用的方法。随着经验的丰富,我学会了将代码封装到对象中,将数据与逻辑分离,重构公共代码并实践其它良好的编程公认原则。
web 开发人员接受 mvc
眨眼到了 1994 年,当时主流的采用 web 应用程序的开发才刚开始。由于 web 的不成熟,只有较少的工具能帮助开发人员构建 web 软件。结果,在特定解决方案中的应用程序混合了 html 代码与应用程序逻辑。很显然,ui 设计的更改和业务逻辑的更新在大型应用程序中既困难又昂贵,因为紧耦合的表示和逻辑将这两种元素搅和在一起,进而导致错误和缓慢的进展。而且,混合的代码要求部分开发人员具备 ui 设计知识,或者要求开发人员与图形设计人员之间有紧密的工作关系,这常常会造成时间上的浪费。
jsp 技术和标记的引入稍微改善了这种更改问题,因为能够将逻辑和显示分离。ui 设计人员能够对显示进行卓有成效的工作,同时开发人员能够专注于逻辑。然而,这种方法仍存在一些缺陷。尤其是某些操作(还有公共操作)的开发仍很困难。验证表单就是典型的例子。正如很多人所知,表单验证的过程类似于这样:
显示表单;等待用户填写然后提交数据。
检查各域值是否有效;如果有错误,则重新显示表单。
处理用户输入的数据,可能将其存储在一个数据库中。
在新页面上向用户显示处理的结果或下一步(可能是另一个表单)。
如果在这一过程中只使用 jsp 页面,那么在需要再次更改代码时,您会发现,按照可管理性这条思路,将控制从一个页面“路由”至另一个页面很难。您想把第 4 步和第 3 步置于同一个页面吗?如果使用多个单独的 jsp 页面,那么如何跟踪哪个页面链接至其它页面,以及在要更改一个页面的文件名或位置时该怎么做呢?而且,在第 2 步检测到某个域中的错误时,如何重新显示带有一条错误消息的原始表单,但还要保留用户已填入的值呢?struts,一种开放源码“模型-视图-控制器”框架,通过帮助解决所有这些问题,从而使开发人员的工作更为轻松。
本文并不深入讨论 mvc 平台。有关这方面的信息,请参阅 malcolm davis 所写的标题为“struts, an open-source mvc implementation”的 developerworks 文章。您正在阅读的这篇文章讨论自 malcolm 的文章发表以来对 struts 所做的更改,包括 tiles 库。至于代码的安装过程,本文仅涉及 jakarta tomcat 4.0(catalina)最小安装所需的步骤。如果您没有使用 tomcat,请查阅手册以了解您的应用程序服务器。
struts 和 tiles 的背景知识
craig mcclanahan 是 apache tomcat 项目的技术主管,他创立 struts 项目以满足对这方面的渴望。它作为“模型-视图-控制器”框架首选的并经过正式认可的开放源码实现,已经越来越流行了。它以与交付产品一起分发的形式受到来自 sun 和 ibm 的支持。因为 craig 积极参与 tomcat 和 struts 的开发工作,所以 struts 将继续与 jsp 和 servlet 规范的参考实现高度兼容,进而与所有 j2ee 应用程序服务器高度兼容。
malcolm davis 的有关 struts 的 developerworks 文章涵盖了整个 struts 0.9 的功能;为了简短起见,我将只讨论对 struts 0.9 的更改以及他未涉及的 struts 主题。目前的 struts 发行版本是 1.0.2,但自 2002 年 3 月 19 日起有一个标记为 1.1-b1 的 beta 测试版可供使用。因为 beta 测试版表示编码工作已经完成,在这种情况下只进行错误修正,所以极有可能 1.1 的最终版本不久就将面市,而在 struts 邮件列表上已经有这种呼声。因此,任何利用 struts 的新项目很可能都将 1.1 代码作为基础,而这就是我将讨论的内容。
自版本 0.9 以来对 struts 框架的有用添加包括经改进的表单验证功能、可以通过 xml 声明来指定表单元素和可以动态地定义 bean 特性。然而,最重要的添加可能是将 tiles 模板库合并到 struts 分发版中。
您是否曾希望用一种更简便的方法创建一组页面(或可能是整个应用程序),并且每个页面上的用户界面保持一致 ? 有相同的导航栏、页眉和页脚等等?在含有较多内容的页面内显示多个类 portlet 的矩形内容的方法又如何?在 tiles 框架的帮助下,您可以完成这两项任务和其它更多任务。通过定义屏幕和一组可嵌入在 jsp 页面中的标记的核心 xml 文件来插入静态和动态内容,tiles 框架允许您构建组件化的视图,并按您的希望来组装它们,从而有助于提高灵活性、可重用性、一致性和可维护性。
struts 和 tiles 之间交互良好,因为这两个项目的开发人员已经认识到这两者具有互补性,所以决定让这两者共同协作。开发人员可以指定 tiles 页面定义作为 struts 操作的目标视图(按照 struts 的说法是一个 forward)。因为 struts 和 tiles 都遵循 jsp 标记库规范,所以可以在 jsp 页面中将 struts 标记和 tiles 标记相互混合在一起。
您可能渴望尝试 tiles 框架,并确切地了解它可以做些什么。如果您希望在自己安装本文的示例前先了解这些示例的运行情况,可以看看它们在带有嵌入式 tomcat 的 jboss 服务器上是怎样运行的。
struts 和 tiles 是用于 web 开发的辅助工具,所以您需要设置一个 web 容器对它们进行实验;将 tomcat 设置为您的容器,然后设置 struts 和 tiles 包,我会在下一节中循序渐进地讲述这一过程。这些指导信息还向您展示了如何安装本文的样本代码。一旦完成了这一切,您就准备好继续本文。示例 1 应用程序没有利用 struts 和 tiles;它演示了以页面为中心的方法。通过将它与示例 2 比较,您会看到 struts 和 tiles 将如何极大地提高您的 web 开发的结构化程度和可管理性。最后,示例 3 演示了将功能添加到一个使用 struts 和 tiles 的、并且已经启动且正在运行的 web 应用程序中是多么地简单。
安装 struts 和 tiles
在带有 j2se 1.4 sdk、ant 1.4.1、tomcat 4.0.3 和 struts 1.1-b1 的 linux 机器上,下列指导信息已经经过了测试。如果因这些软件包的版本不同而遇到困难,您可能需要使用上面所指定的版本,以便开始了解 struts 和 tiles 的设置和开发。
如果您没有 j2se 1.4 sdk(java 2 platfrom,标准版 1.4 软件开发工具箱),请从 http://java.sun.com/j2se/1.4/download.html 获取它,然后遵循该软件包中的指导信息来安装它。您需要 sdk 而不只是 jre,但是您可以选择获取 forte/sdk 组合。
确保您的环境变量 java_home 设置为 j2se 1.4 sdk 的安装目录。
如果没有 ant 1.4,请从 http://jakarta.apache.org/builds/jakarta-ant/release/v1.4.1/bin/ 获取二进制分发版,然后将它解压缩。对于 ant 1.4 以及安装指导信息中所要求的所有其它包,请确保获取的都是二进制分发版,而不是源代码;否则,您将不得不在使用它们之前编译这些包。同样,将 ant 的 bin 目录添加到您的路径中。
请从 http://jakarta.apache.org/builds/jakarta-tomcat-4.0/release/v4.0.3/bin/ 获取 tomcat 4.0.3 二进制分发版,然后将它解压缩。文件名应该与 jakarta-tomcat-4.0.3-le-jdk14.tar.gz 相似。为了便于稍后在这些指导信息中引用此名称,让我们暂且任意地将安装目录(至并且包括 tomcat 目录)的路径称为 tomcat_home。在 unix 系统上,该路径类似于 /home/wchao/jakarta-tomcat-4.0.3-le-jdk14,在 windows 系统上类似于 c:jakarta-tomcat-4.0.3-le-jdk14。
请从 http://jakarta.apache.org/builds/jakarta-struts/release/v1.1-b1/ 获取 struts 1.1-b1 beta 测试发行版,然后将它解压缩(不在 tomcat_home 中)。我们称该目录为 struts_install。在 unix 系统上,该目录类似于 /home/wchao/jakarta-struts-1.1-b1,在 windows 系统上类似于 c:jakarta-struts-1.1-b1。
请下载 struts-tiles-examples.tgz,然后将它解压缩。它将创建三个目录:ex1、ex2 和 ex3。我们分别称这些目录为 ex1_install、ex2_install 和 ex3_install。
转至 tomcat_home/bin 目录。
通过输入 ./startup.sh(如果在运行 unix)或 ./startup.bat(如果在运行 windows)来启动 tomcat 服务器。
将 web 浏览器指向 http://localhost:8080/examples 来验证 tomcat 是否已启动并正确运行。缺省情况下,tomcat 附带了 examples 应用程序。如果 examples 不工作,则 tomcat 发生故障;请参阅 tomcat 文档来解决问题。
hello, world:首次尝试
要研究我们第一个示例,请遵循下列步骤:
转至 ex1_install 目录。
编辑 build.xml 文件,为 tomcat.install.dir 填写适当值。尽管该值可以是绝对路径,也可以是相对路径;但如果您不了解 ant 是如何工作的,或许最好使用绝对路径。
输入 ant deploy。这将把第一个示例应用程序构建到 war 文件中,以备部署,然后将它部署至 tomcat。如果得到一个指出无法找到 ant 的错误,请参阅“安装 struts 和 tiles”一节中的第 3 步,并确保您的路径环境变量包含 ant。
将 web 浏览器指向 http://localhost:8080/ex1。您应该会看到“hello, world”页面。
示例 1 web 应用程序非常简单,它演示了常见的 web 应用程序功能。几乎所有应用程序(也包括这个最简单的应用程序)都要求所有页面具有一致的用户界面。通常,这意味着所有页面都有公共的徽标、顶部栏、上部或左侧导航栏、主体和页脚。在示例 1 中,我有意对每一页面中的公共项进行硬编码,以便说明这一点。web 应用程序开发的新手一般会通过将现有代码复制粘贴到新文档中来添加新的功能页面。很容易预见这种方法难以应付将来的变化。随着每一次增加新内容,更改诸如菜单、徽标等公共页面元素的过程花的时间会更长,更容易出错。很明显,复制粘贴方法对于任何具有大量页面的应用程序是一个糟糕的模型。
敏锐的读者会认识到 jsp 技术提供了包括来自其它 servlet 和页面中的内容的功能。我们为什么不可以仅仅使用 <jsp:include/> 标记来合并公共元素呢?这肯定会使那些元素更易于更改。如果您需要更改菜单,只要更改包含菜单的文件。所有其它页面只需使用 <jsp:include/> 标记就可以得到菜单中的内容,这样这些页面可以自动获得对菜单的更改。但是,当需要更改实际布局或需要重新组织文件和目录时,这种方法有不足之处。当决定更改以页面为中心模型下的布局时,必须对每个单个页面进行更改,因为即使对公共元素的访问已做了集中化处理,但仍然是由每个页面中的 html 代码来描述布局本身(有哪些是元素及它们的位置)。同样地,当决定更改包含了某个公共元素内容的文件的文件名或位置时,必须逐个更改使用该元素的文件。什么原因呢?因为每个文件根据固定的物理文件名,而不是逻辑对象名来查找每个公共元素。因此,必须更新每个对物理文件名的引用。tiles 视图组件可以解决这些问题。
如果更进一步地研究 index.jsp 和 form1.jsp(这两个 jsp 文件构成该应用程序),会发现另一个缺点:错误处理相当笨拙。错误处理代码是在 form1.jsp 中,其中我必须重复显示代码,并添加代码以插入用户在前一表单屏幕(index.jsp)中输入的值。如果用户概要信息域曾更改过,或者如果输入表单的显示曾更改过,就必须更新这两个地方中的代码。我可以将 form1.jsp 的错误处理部分与 index.jsp 中的初始表单显示结合在一起,但在初始表单装入时,我仍将需要做额外的工作以把域值设置成空字符串,并且我仍将需要有一个物理文件名来表示用户概要信息的最终静态显示,这意味着发生更改时,该应用程序结构仍是很脆弱的。struts 表单自动化可以解决这种笨拙的表单处理缺陷。
下表 1 总结了由示例 1 应用程序演示的基于 jsp、以页面为中心的 web 应用程序模型的优缺点。
表 1. 基于 jsp 方法的概述
优点 说明
入门容易。 只要设置 tomcat,然后就可以开始编写代码。不需用核心文件来保持同步,也不需要冗长的库初始配置。由每个单独的 jsp 页面或 servlet 来指定连接。
缺点 说明
在应用程序的不同部分中重用表示很困难。 一定程度上,可以使用 <jsp:include/> 标记来解决一部分重用,但它们在管理更改方面不能很好地工作。
公共输入和数据处理任务枯燥且重复。 错误处理是普通 jsp 页面的常见问题。而且,必须手工填入表单值及手工检索请求对象中的那些值,这是一件既耗时又枯燥的工作。
业务逻辑和表示紧密耦合在一起,从而将两者的代码混合在一起。 如果研究一下 index.jsp 和 form1.jsp,就会发现 java 代码是与 html 代码混在一起的。代码很难看,易于出错,而且要做到使 java 编码或用户界面开发分离开非常困难。最终不得不同时了解 html 和 java 编码对页面的作用。
没有对应用程序流或行为的集中描述。 除非逐个查看页面,否则根本无法了解应用程序的整体印象以及操作流是怎样运作的。随着项目越来越大,容易造成错误、失败和令人迷惑的地方。
hello, world:经改进的新的应用程序
现在,让我们研究刚才看到的 web 应用程序示例中的 struts 和 tiles 版本。请执行下列步骤:
转至 ex2_install 目录。
编辑 build.xml 文件,为 struts.install.dir 和 tomcat.install.dir 填写适当的值。
输入 ant deploy。这将把第二个示例应用程序构建到 war 文件中以备部署,然后将它部署至 tomcat。如果看到关于无法复制文件的错误,请检查第 2 步以确保正确设置了 struts.install.dir 和 tomcat.install.dir。
将 web 浏览器指向 http://localhost:8080/ex2。您应该会看到“hello, world”页面。
目录结构和文件的说明
在 ex2_install/src/web 目录下有不少文件,乍看起来可能会把人搞糊涂。以下是给大家的一些指导。
profileinput.jsp 和 profileoutput.jsp 页面是页面主体 panel3 的内容;它们驱动这一特殊应用程序。在 tiles-components 下有页面的各种组件,而在 tiles-layouts 下是有关布局的 html 代码。我喜欢这样的组织安排,因为这使得对不同的用户角色有不同的布局,并在一个中心位置中保存所有视图组件。tiles 可以让您以您希望的任何方式安排文件,只要您在 tiles-defs.xml 文件中指定了如何组织事物,所以使用那些最适合于您工作的事物。
如果您已看过 ex2_install 目录,您很可能会说:“这里要做些什么呢?有好多文件。”与大多数强调更有序和结构化程度更高的技术一样,对于 struts 和 tiles,在一开始需要在管理文件上花些工夫。对于只有少许页面的小项目,这一额外开销可能微不足道。然而,随着项目变大,struts 和 tiles 方法逐渐会显示其优越性。让我们一点点地体会吧!这里我不想讨论 ex2_install/src/web-inf/web.xml;尽管这个文件实质上与其示例 1 中相对应的文件不同,而且大多数行都是样板,但理解这些设置对于着手开发并不太重要。
在 ex2_install/src/web-inf/struts-config.xml 中,自先前有关 struts 的文章以来重要的更改有在 <form-beans/> 节中 dynaactionform 的使用及在 <action-mappings/> 节中 tile 作为目标的使用。在 struts 的以前版本中,您必须为每个所使用的表单 bean 定义一个 java 类。仅当不同的 html 表单共享域时,才可以在这些表单之间共享表单 bean。总之,每个表单 bean 需要有一个 java 类是一个非常麻烦的要求。现在,您可以在 struts-config.xml 文件中指定表单 bean 的特性,而且是迅速地!不必有保存 java 类的单独文件,就能自动创建这种 bean。象处理 hashtable 对象一样,用值的强类型对象来处理动态表单 bean。至于操作映射,一旦确定将 tiles 库合并到 struts 分发版之后,那么指定一个 tile 作为目标,就完全是增加一项逻辑而已。您会在概要信息表单的操作映射中看到 tile 目标(tile.profileinput 和 tile.profileoutput)。在 input 属性和 path 属性中指定 tile。注:可以指定 tile 目标弥补了我在分析以页面为中心的模型中提到的更改文件名和位置中的缺陷:tile 目标是虚拟名称或逻辑名称,而不是物理名称。
现在,进入激动人心的部分。让我们看一下 ex2_install/src/web-inf/tiles-defs.xml。
在 <definition/> 标记中指定 tile。您可以将定义命名为任何希望的名称,而且 name 属性不必是与 path 属性匹配的子字符串。我为第一个定义选择了名称 rootlayout,以表明它是应用程序中的页面要遵循的基本布局。注:路径是 /tiles-layout/rootlayout.jsp。如果查看 ex2_install/src/web 下的 /tiles-layout/rootlayout.jsp,您会看到这种布局是多么的简单整齐。用户界面的设计人员会“爱上它”。还请注意:它不包含任何代码,所以用户界面设计人员在进行更改时不必担心破坏什么。
rootlayout.jsp 中的 <tiles:insert/> 标记对应于 tiles-defs.xml 中 rootlayout 定义内的 <put/> 标记。注:每个 <tiles:insert attribute="x"/> 标记都有一个表示逻辑名称的属性。每个逻辑名称映射至通过在 tiles-defs.xml 内的 <definition/> 中使用 <put name="x" value="y"/> 标记指定的名称和值。通过在 rootlayout.jsp 页面中使用逻辑名称,而非物理名称,并通过在 tiles-defs.xml 中统一物理名称,我们就可以更改文件名,并使项目文件系统的组织易于管理。
真正节省时间和适应性方面最显著的增强方面体现在布局的继承,这是 struts 的另一个特性。在 tiles-defs.xml 中,“page definitions”栏下面的节有两个页面:tile.profileinput 和 tile.profileoutput。这些名称是任意的,如果您不喜欢 tile. 前缀,可以不使用它(但是您使用的名称必须与 struts-config.xml 文件中指定的目标相匹配)。这些名称应该与 struts-config.xml 中 <forward name="x" path="y"/> 标记中的 path 属性匹配。这些名称还应该与 struts-config.xml 中 <action … input="" …/> 标记中的 input 属性匹配。在开发用户界面时,<definition name="x" extends="y"/> 标记中的 extends 属性是体现开发灵活性的地方。通过指定主布局并扩展它,您不仅能灵活更改象 topbanner、topmenu、panel1、panel2 这样的公共元素及其它组件, 还能随意地将不同元素放在页面上及更改它们的位置。例如,您可以添加 panel4(一个 tile)以在页面左侧的 panel2 下显示本地天气。只要天气代码不需要用户的任何输入或与页面上的其它组件交互,您就可以添加 panel4 而不必对应用程序业务逻辑做任何更改,甚至不必更改除 rootlayout.jsp 以外的 jsp 页面。
让我们尝试将带有天气信息的 panel4 添加至应用程序中来看看这样做是多么容易。为了节省时间,我已在 ex2_install/src/web/tiles-components 中名为 panel4.jsp 的文件中创建了天气组件的 jsp 文件,其中有内容和 html 代码。您需要进行两个更改:
在 ex2_install/src/web-inf/tiles-defs.xml 中,找到清单 1 中显示的代码,然后编辑它以添加用于 panel4 的 <put/> 标记,如清单 2 所示:
清单 1. 原始 tiles-defs.xml 代码
<definition name="rootlayout" path="/tiles-layouts/rootlayout.jsp">
<put name="titlestring" value="change-me"/>
<put name="topbanner" value="/tiles-components/topbanner.jsp"/>
<put name="topmenu" value="/tiles-components/topmenu.jsp"/>
<put name="panel1" value="/tiles-components/panel1.jsp"/>
<put name="panel2" value="/tiles-components/panel2.jsp"/>
<put name="panel3" value="change-me"/>
<put name="footer" value="/tiles-components/footer.jsp"/>
<put name="footerdebug" value="/tiles-components/footerdebug.jsp"/>
</definition>
清单 2. 新的 tiles-defs.xml 代码
<definition name="rootlayout" path="/tiles-layouts/rootlayout.jsp">
<put name="titlestring" value="change-me"/>
<put name="topbanner" value="/tiles-components/topbanner.jsp"/>
<put name="topmenu" value="/tiles-components/topmenu.jsp"/>
<put name="panel1" value="/tiles-components/panel1.jsp"/>
<put name="panel2" value="/tiles-components/panel2.jsp"/>
<put name="panel4" value="/tiles-components/panel4.jsp"/>
<put name="panel3" value="change-me"/>
<put name="footer" value="/tiles-components/footer.jsp"/>
<put name="footerdebug" value="/tiles-components/footerdebug.jsp"/>
</definition>
在 ex2_install/src/web/tiles-layouts/rootlayout.jsp 中,找到清单 3 中显示的代码,然后编辑它以添加 <br> 标记和代码来插入 panel4,如清单 4 所示:
清单 3. 原始 rootlayout.jsp 代码
<td width="35%">
<!– ============================================================ –>
<!– begin panel1 –>
<tiles:insert attribute="panel1"/>
<!– end panel1 –>
<!– ============================================================ –>
<br>
<!– ============================================================ –>
<!– begin panel2 –>
<tiles:insert attribute="panel2"/>
<!– end panel2 –>
<!– ============================================================ –>
</td>
清单 4. 新的 rootlayout.jsp 代码
<td width="35%">
<!– ============================================================ –>
<!– begin panel1 –>
<tiles:insert attribute="panel1"/>
<!– end panel1 –>
<!– ============================================================ –>
<br>
<!– ============================================================ –>
<!– begin panel2 –>
<tiles:insert attribute="panel2"/>
<!– end panel2 –>
<!– ============================================================ –>
<br>
<!– ============================================================ –>
<!– begin panel4 –>
<tiles:insert attribute="panel4"/>
<!– end panel4 –>
<!– ============================================================ –>
</td>
注:ex3_install 中的示例 3 应用程序只是示例 2 加上前面所做的更改;如果有问题,可以使用该代码。
现在,需要执行一些步骤使 tomcat 识别新文件:
转至 tomcat_home/bin 目录。
通过输入 ./shutdown.sh(如果在运行 unix)或 ./shutdown.bat(如果在运行 windows)来关闭 tomcat 服务器。
转至 ex2_install 目录。
输入 ant undeploy,以从 tomcat webapp 目录中除去 ex2.war 文件和解压的 ex2 目录。
输入 ant deploy。
转至 tomcat_home/bin 目录。
通过输入 ./startup.sh(如果在运行 unix)或 ./startup.bat(如果在运行 windows)来启动 tomcat 服务器。
将 web 浏览器指向 http://localhost:8080/ex2。重新将页面装入浏览器,以确保您看到的不是示例 2 web 应用程序的高速缓存副本。您应该会看到新的带有天气组件的“hello, world”页面。
示例 2 应用程序说明了下表 2 中所总结的基于 mvc 的 struts 和 tiles web 应用程序模型的优缺点。
表 2. struts 和 tiles 方法的概述
缺点 说明
陡峭的学习曲线,要处理较多的移动部件操作。 struts 和 tiles 的入门要比普通 jsp 页面花费的时间长,部分是因为要处理更多的文件和需要进行额外配置。
优点 说明
维护更容易,模块化程度更高。 tiles 框架使得添加和除去视图组件及重新安排事物非常容易。struts 执行类似的行为和业务逻辑功能。
为公共的输入和输出任务预先构建的解决方案。 利用 struts,您可以自动接受表单并处理错误,并以结构化的方法进行。tiles 框架让您方便地将不同的输出窗格组装成一个集成的整体。
易于并行地进行业务逻辑和 ui 开发。 因为业务逻辑与显示相分离,所以在 java 开发人员开发业务逻辑的 java 代码同时,图形设计人员可以开发用户界面的 html。
操作、表单和屏幕的集中映射。 由 struts-config.xml 文件和 tiles-defs.xml 文件提供了操作、表单和屏幕的集中映射,这更易于理解整个应用程序,特别是在应用程序很大的情况下。
struts 和 tiles 更复杂的使用
篇幅所限,不允许我再深入讨论 struts 和 tiles 包其它一些实用的方面,但我真的想简要地谈一下,这样您可以对 struts 和 tiles 可以做些什么有所了解。如果有足够的需求,可能这些内容会是将来文章的主题。
您会在本文的两个示例中注意到,我编码了名、姓、喜欢的颜色和出生日期等基本验证。我所采用的这类简单验证实际上可由 struts 通过使用它的格式验证来执行,这样节省了花在编码 java 语句的时间。例如,检查是否是空字符串、检查字符串是否与日期相匹配或检查是否与其它某些正则表达式匹配等,这都是可行的。您会发现将格式验证用作第一级检查会是十分方便的,在检查是否符合更复杂的业务逻辑规则之前,程序可用第一级检查来消除一些明显错误。struts 提供了一个验证器包,可以通过 web-inf 目录中的 validator.xml 描述符来配置该包。在这两个示例中我没有包含该验证器包;如果您想试一下,它包含在 struts 1.1-b1 包中。
struts 和 tiles 包的另一个有用特性是与容器管理的安全性相集成。很多人都在使用诸如 ibm websphere 或 jboss 之类的应用程序服务器。这些服务器通过处理安全性中所涉及的许多日常任务使认证和授权更便捷,让您摆脱必须对它们进行的编码。struts 允许您根据用户角色有条件地向不同用户显示 bean 数据的不同位,这可以通过自动查询容器来决定。同样地,tiles 框架允许您根据用户角色有条件地向不同用户显示不同的视图组件,这也是通过自动查询容器来决定的。我在自己的应用程序中使用这些特性向管理员、常规用户或 guest 用户显示不同的菜单。
最后要说明,我在示例中没有谈到国际化,但对于那些构建将来最终要以多种语言发布的大型应用程序的人来说,这实际是一个重要方面。struts 让您创建消息资源特性文件,这些文件指定标签、标题和其它输出的文本。如果您用几种不同语言的输出填入消息资源特性文件的话,只要简单更改语言设置就能将所有窗口构件和硬编码的文本更改成适当语言,甚至在应用程序运行中也可以更改。
未来的方向
struts 和 tiles 将走向何方呢?刚出现的两个更改必定会使 struts 和 tiles 更加有用。第一个更改是工作流管理系统。您很可能处理过许多多步骤的业务过程;目前,在 web 应用程序中对它们进行编码可以是一个主要的麻烦,因为您必须协调不同的步骤,而每一步骤都是 java 类中的一个单独方法或是一个单独的 servlet 或 jsp 页面。商业市场中的工具通过使开发人员能对多步骤的业务过程进行建模,然后自动生成 java 代码作为进一步开发的基础,来帮助管理这些过程。struts 工作流管理系统将提供类似的功能,使开发人员能够编写业务过程的脚本,这些过程在 web 应用程序中跨多个页面,并指定这些页面如何通过核心的基于规则的系统进行交互。
另一个同样有望即将出现的更改是将 struts 标记合并到 jsp 标准标记库(jsp standard tag library)中,这个库是 jakarta 项目,它试图产生一个有用的定制标记集合,从而简化并加快用 jsp 页面编写 web 应用程序的开发。其中的意义在于:web 应用程序的开发将比过去任何时候都更容易,因为您可以通过使用定制标记的标准机制得到一个在此基础上做进一步开发的预先编写好的代码库。而且,jsp stl 标准中这个项目的合并甚至确保了 struts 和 tiles 功能更为广泛的分发和可用,这意味具有这种技能的开发人员在众多项目中大有作为,而且公司更加容易获得开发 web 应用程序的熟练人才。
您能从本文中获得什么?
在阅读了本文后,您应该记住以下要点:
mvc 是开发健壮的 web 软件的优秀体系结构。面向页面的体系结构是简单的,但随着应用程序在规模和使用范围方面的增长会逐渐失去作用。mvc 是一种经证实适合于较大型应用程序的模型。
struts 和 tiles 为复杂应用程序提供一个坚实的基础。struts 和 tiles 符合 mvc 范例,并允许开发人员创建随业务需要在管理状态下增长的应用程序。
struts 和 tiles 受到强大的业界支持,并在开发人员中有逐渐流行和具有推动力。这确保了其被广泛采用,并保护了开发人员和公司投入的时间和金钱。
有了 struts 和 tiles,您会发现现在创立您自己的 web 应用程序更加容易了。
参考资料
请通过单击文章顶部或底部的讨论,参与关于本文的论坛。
下载以 zip 文件或 tgz 文件形式提供给大家的本文中的示例代码。
在 jakarta struts 主页上查找更多有关 struts 的信息。
研究 tiles 并查找文档。
如有疑问,可以通过这些邮件列表 struts-user、tomcat-user、commons-dev 和 taglibs-user 寻求帮助,这些邮件列表都位于 jakarta 站点。
获得 tomcat jsp/servlet。
要了解有关实用开放源码库 taglibs 的更多信息,请访问 jakarta taglibs 站点。
有关 struts 的入门级简介,请参阅 malcolm davis 所写的“struts, an open-source mvc implementation”(developerworks,2001 年 2 月)。
在 ibm visualage 开发者园地中还有一篇非常好的关于带有 ibm 工具的 struts 的参考文章,它是由 kyle brown 所写的“apache struts 与 visualage for java,第一部分:使用 apache struts 构建基于 web 的应用程序”(2001 年 5 月)。
如果您希望了解有关“模型-视图-控制器”框架的更多背景知识,请查看 wayne beaton 的“migrating to ibm websphere application server, part 1: designing software for change”(websphere developer technical journal,2001 年 7 月)。
ibm websphere 是一个功能齐全的出色的应用程序服务器;一旦您的应用程序开发比本文中的简单示例更复杂,就会需要这样一个服务器。
jboss 是一个也能满足应用程序开发需要的开放源码的应用程序。
下载 j2se 1.4 sdk。
从 jakarta 站点上 ant 1.4 构建工具的主页上获取该工具。
在 developerworks java 技术专区可以找到其它 java 技术参考资料。
