1.2 Struts的体系结构
Struts 有一组相互协作的类、 Serlvet 以及 Jsp TagLib 组成。基于 Struts 构架的 web 应用程序基本上符合 JSP Model2 的设计标准,可以说是 MVC 设计模式的一种变化类型。根据上面对 framework 的描述,我们很容易理解为什么说 Struts 是一个 web framwork ,而不仅仅是一些标记库的组合。但 Struts 也包含了丰富的标记库和独立于该框架工作的实用程序类。
Struts 有其自己的控制器( Controller ),同时整合了其他的一些技术去实现模型层( Model )和视图层( View )。在模型层, Struts 可以很容易的与数据访问技术相结合,包括 EJB,JDBC 和 Object Relation Bridge 。在视图层, Struts 能够与 JSP, Velocity Templates,XSL 等等这些表示层组件想结合。
1.2.1 Struts的与Web App的关系
既然
struts
叫做
web framework
,那么其肯定主要基于
web
层的应用系统开发。按照
J2EE Architecture
的标准,
struts
应当和
jsp/servlet
一样,存在于
web container
一层。
1.2.2 Struts 的体系结构
Struts 是一个基于 Sun J2EE 平台的 MVC 框架,主要是采用 Servlet 和 JSP 技术来实现的。其最初萌芽于 Craig McClanahan 的构思, 2000 年 1.0 版本诞生至今年已经快 10 年了。现在, Struts 是 Apache 软件基金会旗下 Jakarta 项目组的一部分,其官方网站是 http://jakarta.apache.org/struts 。由于 Struts 能充分满足应用开发的需求,简单易用,敏捷迅速,一直是 WEB 开发的主流框架。 Struts 把 Servlet 、 JSP 、自定义标签和信息资源 (message resources) 整合到一个统一的框架中,开发人员利用其进行开发时不用再自己编码实现全套 MVC 模式,极大的节省了时间,所以说 Struts 是一个非常不错的应用框架。
我们说 struts framework 是 MVC 模式的体现,下面我们就从分别从模型、视图、控制来看看 struts 的体系结构( Architecture )。下图显示了 struts framework 的体系结构响应客户请求时候,各个部分工作的原理。
Struts 的体系结构实现了 Model-View-Controller 设计模式的概念,它将这些概念映射到 web 应用程序的组件和概念中,如下图所示:
1.2.3 Struts 的基本组件包
整个 struts 大约有 15 包,近 200 个类所组成,而且数量还在不断的扩展。在此我们不能一一介绍,只能列举几个主要的简要的介绍一下。下表说明了目前 struts api 中基本的几个组件包,包括 action,actions,config,util,taglib,validator 。下图则显现了这几个组件包之间的关系。其中 action 是整个 struts framework 的核心
org.apache.struts.action |
基本上,控制整个 struts framework 的运行的核心类、组件都在这个包中,比如我们上面提到的控制器 ActionServlet 。已经有 Action,ActionForm,ActionMapping 等等。 struts1.1 比 1.0 多了 DynaActionForm 类。增加了动态扩展生成 FormBean 功能 |
org.apache.struts.actions |
这个包是主要作用是提供客户的 http 请求和业务逻辑处理之间的特定适配器转换功能,而 1.0 版本中的部分动态增删 FromBean 的类,也在 struts1.1 中被 Action 包的 DynaActionForm 组件所取代 |
org.apache.struts.config |
提供对配置文件 struts-config.xml 元素的映射。这也是 sturts1.1 中新增的功能 |
org.apache.struts.util |
Struts 为了更好支持 web application 的应用,体统了一些常用服务的支持,比如 Connection Pool 和 Message Source 。详细信息请参考 http://jakarta.apache.org/struts/api/org/apache/struts/util/package-summary.html |
org.apache.struts.taglib |
这不是一个包,而是是一个客户标签类的集合。下面包括 Bean Tags , HTML Tags , Logic Tags , Nested Tags , Template Tags 这几个用于构建用户界面的标签类。 |
org.apache.struts.validator |
Struts1.1 framework 中增加了 validator framework ,用于动态的配置 from 表单的验证。 |
Struts 的基本组件关系图
Struts 的框架可分为以下四个主要部分,其中三个就和 MVC 模式紧密相关:可分为以下四个主要部分,其中三个就和 MVC 模式紧密相关:
1. 模型 (Model) ,本质上来说在 Struts 中 Model 是一个 Action 类 ( 这个会在后面详细讨论 ) ,开发者通过其实现商业逻辑,同时用户请求通过控制器 (Controller) 向 Action 的转发过程是基于由 struts-config.xml 文件描述的配置信息的。
2. 视图 (View) , View 是由与控制器 Servlet 配合工作的一整套 JSP 定制标签库构成,利用她们我们可以快速建立应用系统的界面。
3. 控制器 (Controller) ,本质上是一个 Servlet ,将客户端请求转发到相应的 Action 类。
4. 一堆用来做 XML 文件解析的工具包, Struts 是用 XML 来描述如何自动产生一些 JavaBean 的属性的,此外 Struts 还利用 XML 来描述在国际化应用中的用户提示信息的 ( 这样一来就实现了应用系统的多语言支持 ) 。
好,下一步咱们来看看构成这个框架的各个部分以及相互之间是怎样运作的吧!
在使用 Struts 之前,咱们必先设置好 JSP 服务器,以便让服务器在用户请求时,知道该如何将指定后缀的请求转到相应的 Controller - Struts ActionServlet 处理,当然,这些配置信息都一般在服务器启动时通过 web.xml 文件读入的。我们可以在 web.xml 定义多个 Controlloer ,为每一个应用定义一个。一个典型的 web.xml 文件配置如下,其中有相应的注释,很好懂的,在后面讨论 Action 的时候,我们将主要分析 struts-config.xml 。
<web-app>
<servlet>
<!--
以下配置信息声明了 Struts 中的 ActionServlet ,即一个名为 OreillyAction 的 Servlet ,其具体实现为 org.apache.struts.action.ActionServlet 。在这个配置中还有这个 Servlet 的两个参数: debug level 和 detail ,此处这两个参数的值都设为了 2 ,此外还设置了在启动载入时创建两个实例。
-->
<servlet-name>OreillyActionServlet</servlet-name>
<servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
<init-param>
<param-name>config</param-name>
<param-value>/WEB-INF/struts-config.xml</param-value>
</init-param>
<init-param>
<param-name>debug</param-name>
<param-value>2</param-value>
</init-param>
<init-param>
<param-name>detail</param-name>
<param-value>2</param-value>
</init-param>
<load-on-startup>2</load-on-startup>
</servlet>
<!--
设置所有后缀为 .action 的请求,都转发到 OreillyActionServlet
-->
<servlet-mapping>
<servlet-name> OreillyActionServlet </servlet-name>
<url-pattern>*.action</url-pattern>
</servlet-mapping>
<!--
将初始请求页面设置为 login.jsp
-->
<welcome-file-list><welcome-file>login.jsp</welcome-file></welcome-file-list>
<!--
设置 Struts 的 JSP 页面要用到的标签库和她们的路径
-->
<taglib>
<taglib-uri>/WEB-INF/struts-bean.tld</taglib-uri>
<taglib-location>/WEB-INF/struts-bean.tld</taglib-location>
</taglib>
<taglib>
<taglib-uri>/WEB-INF/struts-html.tld</taglib-uri>
<taglib-location>/WEB-INF/struts-html.tld</taglib-location>
</taglib>
<taglib>
<taglib-uri>/WEB-INF/struts-logic.tld</taglib-uri>
<taglib-location>/WEB-INF/struts-logic.tld</taglib-location>
</taglib>
</web-app>
1. 控制器 (Controller)
Controller 是这个框架中扮演“交通警察”的角色,当客户端与服务器有交互动作时,都由她来控制。 Controller 将 HTTP 请求封包并转发到框架中相应的对象,这些对象可能是一个 JSP 页面或一个 Action 。
Controller 在 web.xml 中设置为 org.apache.struts.action.ActionServlet 的一个实例,在本例中,这个实例就是 OreillyActionServlet 。在一个完整的控制过程中,也就是处理一个 HTTP 请求时,在控制过程之初,这个 Servlet 会从一个配置文件 struts-config.xml 中获取请求与控制动作向对应的配置信息,这个我们会在后面详细讨论, Controller 通过这些配置信息来决定 HTTP 请求该往何处转发,而这些 Action 在接收到转发来的请求后,实现真正的商业逻辑。我们要注意的非常重要的一点是 Action 对象要能够调用这个 ActionServlet 的若干方法,通过这个有力的特性,当 Action 对象在控制过程中将请求再向别的 Action 对象转发时 ( 最初的请求是由 ActionServlet 获取,向 Action 对象转发,而 Action 对象还可以再转发到别的对象 ) ,我们可以将一些需要共享的数据对象通过调用一些方法放入这个 Servlet 相关的一些标准容器中捎带过去。
2. 模型 (Model)
所谓 Model 就是在对用户请求的整个控制过程中,真正处理用户请求并保存处理结果的对象,在整个过程中,我们一般利用 JavaBean 来把一些信息保存起来以便在各个对象之间传递。因为在框架中, Model 对象是真正处理商业逻辑功能的对象,因此也就是框架中应用需求实现相关性最大的部分。在 Struts 的实现里, Model 的具体表现形式就是 ActionForm 对象和与其对应的 Action 对象了。对用户提交表单的数据进行校验,甚至对数据进行预处理都能在 ActionForm 中完成。通常的应用中,一般是一个 Model 对象和一个请求页面对应的关系,但也可以一个 Model 对象对应多个页面请求。如果 struts-config.xml 配置文件没有指定一个 Model 对象对应的 Action ,那么控制器将直接把 ( 通过 Model 对象完成数据封装的 ) 请求转到一个 View 对象。
3.struts-config.xml 文件
前面多次提到的 struts-config.xml 配置文件是整个框架的主心骨。 web.xml 文件定义了一个请求到来应向何处转发后,后面的工作就全权由 struts-config.xml 管理控制了。可以说 struts-config.xml 就是整个 Struts 框架的“扛把子” ( 译注 3) ,只有这位“老大”清楚所有请求与动作的映射关系,要是他哪里没有搞定或不爽的话,整个“社团”就什么也摆不平了 :) 如今的应用系统, XML 形式的配置文件越来越多,如果整个系统只使用一个这样的配置文件的话,那么保持整个系统的模块化和可维护性都非常的轻松。使用配置文件来描述请求 - 动作的控制过程和相互关系,而不是在代码中将对象之间的调用关系写死,那么都应用系统有变动时,我们只用修改配置文件就行了,而不是再重新编译发布程序了。
Controller 通过 struts-config.xml 文件的配置信息确定当有请求时应该调用那个对象来处理,从效率的角度出发,这些信息都是在系统启动时读入并存在内存中的。下面我们将讲解一个极短小的 struts-config.xml 文件,文件中定义了一个与登录请求对应的登录动作,请求到达后将被转发到 com.oreilly.ui.authentication.actions.LoginAction 这个 Action 对象,该对象处理的结果决定向用户返回的页面。这个例子同时还示范了一个 Action 对象将请求转发到别的 Action 对象,而例子中另一个返回的对象则是一个 View 对象,即我们看到的 login.jsp 页面。
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts-config PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 1.0//EN"
"http://jakarta.apache.org/struts/dtds/struts-config_1_0.dtd">
<struts-config>
<!-- ========== Action 映射定义 =================== -->
<action-mappings>
<!-- <action> 属性的说明 -->
<!-
type - 完整的 Action 实现类名
name - 该 Action 要用到的 ActionForm 名
path - 请求该 Action 的 URI
unknown – 如果将该属性设置为 true ,那么就是声明这个 Action 将处理整个应用中所有未找到相应处理 Action 的请求,当然,一个应用系统中也只会有一个 Action 的 unknown 属性可以设为 true 了
validate - 如果本属性为 true 则在 Action 动作之前其对应的 ActionForm 的 validate 方法会自动被调用,一般用以校验用户输入的数据
-->
<!-- ~~~~~~~~~~~~~~~~~~~~~ -->
<!-- O'Reilly Main Actions -->
<!-- ~~~~~~~~~~~~~~~~~~~~~ -->
<action path="/Login"
type="com.oreilly.ui.authentication.actions.LoginAction">
<forward name="success" path="/DisplayMainPage.action"/>
<forward name="failure" path="/login.jsp"/>
</action>
</action-mappings>
</struts-config>
4. 视图 (View)
View 对象通常来说都是指的 JSP 页面。 Struts 框架实际上并没有真正的 JSP 的要求规范,而是提供了大量的标签库来为开发者更简便的将 JSP 整合到 Struts 框架中。在 Struts 中通过标签定义方式的 JSP 页面能够将用户通过表单输入的数据存入一个 JavaBean 中,也就是我们前面提到的 ActionForm bean 。通过 Action 类调用 ( 自动或手动 )ActionForm 的校验方法来检查用户输入的数据,如果发现不合法的数据,再通过 Struts 的一个通用机制将错误信息返回给用户显示。
Struts 框架提供了若干个标签库,它们有各自不同的用途。由于这些库还可以脱离 Struts 框架单独使用,这样我们也可以在其他系统中尝试使用这些标签库,它们包括:
* struts-html - 这个标签库用来创建动态的 HTML 页面和表单。
* struts-bean - 提供了类似甚至更强于 <jsp:useBean> 中的功能。
* struts-logic - 用于在页面输出文本信息时的条件、循环等流程的控制。
* struts-template - 用于产生有共同风格的动态 JSP 页面模板。
此外,可定制标签库在 Struts 中还有一大用处是,通过资源文件的方式来实现应用系统的多语言特性,应用 Struts 的系统若想将系统中的用户交互信息换一种语言的会很简单,更换一个不同的资源文件就可以了。
1. 从视图角度( View )
首先, Struts 提供了 Java 类 org. apache.struts.action.ActionForm , Java 开发者将该类细分来创建表单 bean 。在运行时,该 bean 有两种用法:
(1) 当 JSP 准备相关的 HTML ,表单以进行显示时, JSP 将访问该 bean( 它保存要放入表单中的值 ) 。那些值是从业务逻辑或者是从先前的用户输入来提供的。
(2) 当从 Web 浏览器中返回用户输入时,该 bean 将验证并保存该输入以供业务逻辑或 ( 如果验证失败的话 ) 后续重新显示使用。
(3) 其次, Struts 提供了许多定制 JSP 标记,它们的使用简单,但是它们在隐藏信息方面功能强大。例如,除了 bean 名称和给定 bean 中每个段的名称必须相同。 StudentView.jsp :它从 Student.java 获得学生数据来显示。
2 .模型角度( Model )
Struts 虽然不直接有助于模型开发。 在 Struts 中,系统 模型 的状态主要由 ActiomForm Bean 和值对象体现。如: Student.java- 学生信息,它提供一个简单的组件方法来维护学生信息。
3 .控制器角度( Controller )
在 Struts framework 中, Controller 主要是 ActionServlet ,但是对于业务逻辑的操作则主要由 Action 、 ActionMapping 、 ActionForward 这几个组件协调完成(也许这几个组件,应该划分到模型中的业务逻辑一块)。其中, Action 扮演了真正的控制逻辑的实现者,而 ActionMapping 和 ActionForward 则指定了不同业务逻辑或流程的运行方向。 StudentAction.java :用来帮助用户输入数据的确认,并选择哪个 View 来显示结果,如果出错则显示一个错误页面。
总之: model 提供了一个内部数据的表示。 View 不做任何决定,只显示数据。 Controler 决定处理的过程以及下一步要做什么?