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决定处理的过程以及下一步要做什么?