2.2 Struts 的原理
2.2.1 Struts 的起源
Struts 最早是作为 Apache Jakarta 项目的组成部分问世运做。项目的创立者希望通过对该项目的研究,改进和提高 Java Server Pages (JSPs) 、 Servlet 、标签库以及面向对象的技术水准。当前最高发行版本为 Struts1.0.2 ,可以到 http://jakata.apache.org/Struts 下载。
Struts 这个名字来源于在建筑和旧式飞机中使用的支持金属架。它的目的是为了帮助你减少在运用 MVC 设计模型来开发 Web 应用的时间。你仍然需要学习和应用该架构,不过它将可以完成其中一些繁重的工作。如果想混合使用 Servlets 和 JSP 的优点来建立可扩展的应用, Struts 是一个不错的选择。
2.2.2 Struts 工作原理
MVC 即 Model-View-Controller 的缩写,是一种常用的设计模式。 MVC 减弱了业务逻辑接口和数据接口之间的耦合,以及让视图层更富于变化。 MVC 的工作原理 , 如下图 1 所示:
Struts 是 MVC 的一种实现,它将 Servlet 和 JSP 标记(属于 J2EE 规范)用作实现的一部分。 Struts 继承了 MVC 的各项特性,并根据 J2EE 的特点,做了相应的变化与扩展。
Struts 是一组相互协作的类、 servlet 和 JSP 标记,它们组成一个可重用的 MVC 2 设计。这个定义表示 Struts 是一个框架,而不是一个库,但 Struts 也包含了丰富的标记库和独立于该框架工作的实用程序类。图 5 显示了 Struts 的一个概览。
Struts 概览的描述:
(
1
)
Client browser
(客户浏览器)
来自客户浏览器的每个
HTTP
请求创建一个事件。
Web
容器将用一个
HTTP
响应作出响应。
(
2
)
Controller
(控制器)
控制器接收来自浏览器的请求,并决定将这个请求发往何处。就
Struts
而言,控制器是以
servlet
实现的一个命令设计模式。
struts-config.xml
文件配置控制器。
业务逻辑
业务逻辑更新模型的状态,并帮助控制应用程序的流程。就
Struts
而言,这是通过作为实际业务逻辑
“
瘦
”
包装的
Action
类完成的。
(
3
)
Model
(模型)的状态
模型表示应用程序的状态。业务对象更新应用程序的状态。
ActionForm bean
在会话级或请求级表示模型的状态,而不是在持久级。
JSP
文件使用
JSP
标记读取来自
ActionForm bean
的信息。
(
4
)
View
(视图)
视图就是一个
JSP
文件。其中没有流程逻辑,没有业务逻辑,也没有模型信息
--
只有标记。标记是使
Struts
有别于其他框架(如
Velocity
)的因素之一。
2.2.3
详细分析
Struts
图
6
显示的是
org.apache.struts.action
包的一个最简
UML
图。图
6
显示了
ActionServlet (Controller)
、
ActionForm (Form State)
和
Action (Model Wrapper)
之间的最简关系。
ActionServlet
类
您还记得函数映射的日子吗?在那时,您会将某些输入事件映射到一个函数指针上。如果您对此比较熟悉,您会将配置信息放入一个文件,并在运行时加载这个文件。函数指针数组曾经是用
C
语言进行结构化编程的很好方法。
现在好多了,我们有了 Java 技术、 XML 、 J2EE ,等等。 Struts 的控制器是将事件(事件通常是 HTTP post )映射到类的一个 servlet 。正如您所料 -- 控制器使用配置文件以使您不必对这些值进行硬编码。时代变了,但方法依旧。
ActionServlet 是该 MVC 实现的 Command 部分,它是这一框架的核心。 ActionServlet (Command) 创建并使用 Action 、 ActionForm 和 ActionForward 。如前所述, struts-config.xml 文件配置该 Command 。在创建 Web 项目时,您将扩展 Action 和 ActionForm 来解决特定的问题。文件 struts-config.xml 指示 ActionServlet 如何使用这些扩展的类。这种方法有几个优点:
应用程序的整个逻辑流程都存储在一个分层的文本文件中。这使得人们更容易查看和理解它,尤其是对于大型应用程序而言。
网页设计人员不必费力地阅读
Java
代码来理解应用程序的流程。
Java 开发人员也不必在更改流程以后重新编译代码。
可以通过扩展 ActionServlet 来添加 Command 功能。
ActionForm 类
ActionForm 维护 Web 应用程序的会话状态。 ActionForm 是一个抽象类,必须为每个输入表单模型创建该类的子类。当我说输入表单模型时 , 是指 ActionForm 表示的是由 HTML 表单设置或更新的一般意义上的数据。例如,您可能有一个由 HTML 表单设置的 UserActionForm 。 Struts 框架将执行以下操作:
检查
UserActionForm
是否存在;如果不存在,它将创建该类的一个实例。
Struts
将使用
HttpServletRequest
中相应的域设置
UserActionForm
的状态。没有太多讨厌的
request.getParameter()
调用。例如,
Struts
框架将从请求流中提取
fname
,并调用
UserActionForm.setFname()
。
Struts
框架在将
UserActionForm
传递给业务包装
UserAction
之前将更新它的状态。
在将它传递给
Action
类之前,
Struts
还会对
UserActionForm
调用
validation()
方法进行表单状态验证。注:这并不总是明智之举。别的网页或业务可能使用
UserActionForm
,在这些地方,验证可能有所不同。在
UserAction
类中进行状态验证可能更好。
可在会话级维护 UserActionForm 。
注:
struts-config.xml 文件控制 HTML 表单请求与 ActionForm 之间的映射关系。
可将多个请求映射到 UserActionForm 。
UserActionForm 可跨多页进行映射,以执行诸如向导之类的操作。
Action
类
Action
类是业务逻辑的一个包装。
Action
类的用途是将
HttpServletRequest
转换为业务逻辑。要使用
Action
,请创建它的子类并覆盖
process()
方法。
ActionServlet (Command) 使用 perform() 方法将参数化的类传递给 ActionForm 。仍然没有太多讨厌的 request.getParameter() 调用。当事件进展到这一步时,输入表单数据(或 HTML 表单数据)已被从请求流中提取出来并转移到 ActionForm 类中。
注:扩展 Action 类时请注意简洁。 Action 类应该控制应用程序的流程,而不应该控制应用程序的逻辑。通过将业务逻辑放在单独的包或 EJB 中,我们就可以提供更大的灵活性和可重用性。
考虑 Action 类的另一种方式是 Adapter 设计模式。 Action 的用途是 “ 将类的接口转换为客户机所需的另一个接口。 Adapter 使类能够协同工作,如果没有 Adapter ,则这些类会因为不兼容的接口而无法协同工作。 ” (摘自 Gof 所著的 Design Patterns - Elements of Reusable OO Software )。本例中的客户机是 ActionServlet ,它对我们的具体业务类接口一无所知。因此, Struts 提供了它能够理解的一个业务接口,即 Action 。通过扩展 Action ,我们使得我们的业务接口与 Struts 业务接口保持兼容。(一个有趣的发现是, Action 是类而不是接口)。 Action 开始为一个接口,后来却变成了一个类。真是金无足赤。)
Error
类
UML
图(图
6
)还包括
ActionError
和
ActionErrors
。
ActionError
封装了单个错误消息。
ActionErrors
是
ActionError
类的容器,
View
可以使用标记访问这些类。
ActionError
是
Struts
保持错误列表的方式。
图
7. Command (ActionServlet)
与
Model (Action)
之间的关系的
UML
图
ActionMapping
类
输入事件通常是在
HTTP
请求表单中发生的,
servlet
容器将
HTTP
请求转换为
HttpServletRequest
。控制器查看输入事件并将请求分派给某个
Action
类。
struts-config.xml
确定
Controller
调用哪个
Action
类。
struts-config.xml
配置信息被转换为一组
ActionMapping
,而后者又被放入
ActionMappings
容器中。(您可能尚未注意到这一点,以
s
结尾的类就是容器)
ActionMapping 包含有关特定事件如何映射到特定 Action 的信息。 ActionServlet (Command) 通过 perform() 方法将 ActionMapping 传递给 Action 类。这样就使 Action 可访问用于控制流程的信息。
ActionMappings
ActionMappings
是
ActionMapping
对象的一个集合。
核心: Struts 的核心是 ActionSevlet , ActionSevlet 的核心是 Struts-config.xml 。这在后面还会详细讨论。