空间站

北极心空

  BlogJava :: 首页 :: 联系 :: 聚合  :: 管理
  15 Posts :: 393 Stories :: 160 Comments :: 0 Trackbacks

Struts framework 的工作原理和组件

对于 Struts 如何控制、处理客户请求,让我们通过对 struts 的四个核心组件介绍来具体说明。这几个组件就是: ActionServlet Action Classes Action Mapping (此处包括 ActionForward ), ActionFrom Bean

Struts ActionServlet 控制器对象

       ActionServlet 继承自 javax.servlet.http.HttpServlet 其在 Struts framework 中扮演的角色是中心控制器。 它提供一个中心位置来处理全部的终端请求。 控制器 ActionServlet 主要负责将 HTTP 的客户请求信息组装后,根据配置文件的指定描述,转发到适当的处理器。

       按照 Servelt 的标准 所有得 Servlet 必须在 web 配置文件 web.xml 声明。同样 ActoinServlet 必须在 Web Application 配置文件 web.xml 中描述 有关配置信息如下。

<servlet>

<servlet-name>action</servlet-name>

<servlet-class>org.apache.struts.action.ActionServlet</servlet-class>

</servlet>

全部的请求 URI *.do 的模式存在并映射到这个 servlet 其配置如下

<servlet-mapping>

<servlet-name>action</servlet-name>

<url-pattern>*.do</url-pattern>

</servlet-mapping>

一个该模式的请求 URI 符合如下格式:

              http://www.my_site_name.com/mycontext/actionName.do

 

中心控制器为所有的表示层请求提供了一个集中的访问点。这个控制器提供的抽象概念减轻了开发者建立公共应用系统服务的困难,如管理视图、会话及表单数据。它也提供一个通用机制如错误及异常处理,导航,国际化,数据验证,数据转换等。

 

当用户向服务器端提交请求的时候,实际上信息是首先发送到控制器 ActionServlet ,一旦控制器获得了请求,其就会将请求信息传交给一些辅助类( help classes )处理。这些辅助类知道如何去处理与请求信息所对应的业务操作。在 Struts 中,这个辅助类就是 org.apache.struts.action.Action 。通常开发者需要自己继承 Aciton 类,从而实现自己的 Action 实例。

Struts Action Classes

       ActionServlet 全部提交的请求都被控制器委托到 RequestProcessor 对象。 RequestProcessor 使用 struts-config.xml 文件检查请求 URI 找到动作 Action 标示符。

一个 Action 类的角色,就像客户请求动作和业务逻辑处理之间的一个适配器( Adaptor ),其功能就是将请求与业务逻辑分开。这样的分离,使得客户请求和 Action 类之间可以有多个点对点的映射。而且 Action 类通常还提供了其它的辅助功能,比如:认证( authorization )、日志( logging )和数据验证( validation )。

public ActionForward execute(ActionMapping   mapping,

                             ActionForm   form,

                             javax.servlet.ServletRequest   request,

                             javax.servlet.ServletResponse   response)

                      throws java.io.IOException,javax.servlet.ServletException

 

       Action 最为常用的是 execute ()方法。(注意,以前的 perform 方法在 struts1.1 中已经不再支持),还有一个 execute ()方法,请参考 apidoc ,在此不在说明。

       Controller 收到客户的请求的时候,在将请求转移到一个 Action 实例时,如果这个实例不存在,控制器会首先创建,然后会调用这个 Action 实例的 execute ()方法。 Struts Framework 为应用系统中的每一个 Action 类只创建一个实例。因为所有的用户都使用这一个实例,所以你必须确定你的 Action 类运行在一个多线程的环境中。下图显示了一个 execute ()方法如何被访问:

Action 实例的 execute() 方法

      

注意,客户自己继承的 Action 子类,必须重写 execute ()方法,因为 Action 类在默认情况下是返回 null 的。

Struts Action Mapping

上面讲到了一个客户请求是如何被控制器转发和处理的,但是,控制器如何知道什么样的信息转发到什么样的 Action 类呢?这就需要一些与动作和请求信息相对应的映射配置说明。在 struts 中,这些配置映射信息是存储在特定的 XML 文件(比如 struts-config.xml )。  

这些配置信息在系统启动的时候被读入内存,供 struts framework 在运行期间使用。 在内存中,每一个 <action> 元素都与 org.apache.struts.action.ActionMapping 类的一个实例对应。下表就显示了一个登陆的配置映射。

<action-mappings>

  <action  path="/logonAction"

           type="com.test.LogonAction"

           name="LogonForm"

           scope="request"

           input="logoncheck.jsp"

validate="false">

<forward name="welcome" path="/welcome.jsp"/>

<forward name="failure" path="/logon_failure.jsp "/>

</action>

</action-mappings>

 

 

<form-beans>

  <form-bean  name="LoginForm"

type="com.test.LoginForm"/>

</form-beans>

上面的配置表示:当可以通过 /logonAction.do (此处假设配置的控制器映射为 *.do )提交请求信息的时候,控制器将信息委托 com.test.LogonAction 处理。调用 LogonAction 实例的 execute() 方法。同时将 Mapping 实例和所对应的 LogonForm Bean 信息传入。其中 name=LogonForm ,使用的 form-bean 元素所声明的 ActionForm Bean 。有关 form-bean 的申明如下显示。

使用 ActionForward 导航

元素 <forward> 则表示了当 Action 实例的 execute() 方法运行完毕或,控制器根据 Mapping 可将响应信息转到适当的地方。如上面现实,如果客户登陆成功,则调用 welcome forward ,将成功信息返回到 /welcome.jsp 页面。在你的 execute() 方法的结尾可以使用下面的实例代码而返回 welcome forward 。当然你的 welcome forward 必须在 action 元素属性中定义,正如上面所声明的那样。

return (mapping.findForward("welcome"));

 

       ActionForward 对象是配置对象。这些配置对象拥有独一无二的标识以允许它们按照有意义的名称如 “success” “failure” 等来检索。 ActionForward 对象封装了向前进的 URL 路径且被请求处理器用于识别目标视图。 ActionForward 对象建立自 <forward> 元素位于 struts-config.xml 。下面是一个 Struts <forward> 元素例子,属于 <action> 元素范围。

<action path="/editCustomerProfile"

type="packageName.EditCustomerProfileAction"

name="customerProfileForm" scope="request">

<forward name="success" path="/MainMenu.jsp"/>

<forward name="failure" path="/CustomerService.jsp"/>

</action>

       基于执行请求处理器的 execute(…) 方法的结果,当传递一个值匹配指定于 <forward> 元素中 name 属性的值的时候,下一个视图可以在 execute(…) 方法中被开发者用方便的方法 org.apache.struts.action.ActionMapping.findForward(…) 选择。 ActionMapping.findForward(…) 方法既从它的本地范围又从全局范围提供一个 ActionForward 对象,该对象返回至 RequestProcessor RequestDispatcher.forward(…) response.sendRedirect(…) 调用下一个视图。当 <forward> 元素有 redirect=“false” 属性或 redirect 属性不存在的时候, RequestDispatcher.forward(…) 被执行;当 redirect=“true” 是,将调用 sendRedirect(…) 方法。下例举例说明了 redirect 属性的用法:

         <forward name="success" path="/Catalog.jsp" redirect="true"/>

如果 redirect=true, URL 建立如 /contextPath/path 因为 HttpServletResponse.sendRedirect(…) 中解释 URL 采用 ”/” 开头相对于 servlet 容器根目录。

如果 redirect=false, URI 建立如 /path 因为 ServletContext.getRequestDisptacher(…) 采用虚拟目录相关 URL

 

在此稍稍说一下有关 global-forwards 的概念。其在配置文件中描述了整个应用系统可以使用的 ActionForward ,而不是仅仅是一个特定的 Action

   <global-forwards>

    <forward name="logout" path="/logout.do"/>

<forward name="error"  path="/error.jsp"/>

  </global-forwards>

 

Struts ActionForm Bean 捕获表单数据

在上面讲解 ActionServlet Action Classes Action Mapping 的时候,我们都提到了 ActionForm Bean 的概念。一个应用系统的消息转移(或者说状态转移)的非持久性数据存储,是由 ActionForm Bean 的负责保持的。

       ActionForm 派生的对象用于保存请求对象的参数,因此它们和用户紧密联系。

       一个 ActionForm 类被 RequestProcessor 建立。这是发生在已完成向前进到一个 URL ,该 URL 为映射到控制器 servlet 而不是 JSP 和相应的动作映射指定的表单属性的。在这个情况下,如果没有在指定的活动范围内找到, RequestProcessor 将尝试寻找可能导致创建一个新 ActionForm 对象的表单 bean 。该 ActionForm 对象在指定的活动范围内被用 <action> 元素的 name 属性找到;

RequestProcessor 将随后重新安排表单属性,用请求时参数填充表单,随即调用表单对象的 validate(…) 方法以履行服务器端用户输入验证。仅当 ActionMapping 对象中 validate 属性被设为 true 时, validate(…) 方法被调用;这就是默认的行为。 request.getParameterValues(parameterName) 被用于得到一个 String[] 对象,它用来表单填充;验证的结果应该是一个 ActionErrors 对象,用 org.apache.struts.taglib.html.ErrorsTag 来显示验证错误给用户。 ActionForm 也可以被用于为当前用户保存即将被一个视图引用的中间模型状态。

当一个表单对象被 RequestProcessor 找到,它被传递到请求处理器的 execute(…) 方法。一个 ActionForm 对象也可以被请求处理器建立。表单对象建立目的是提供中间模型状态给使用请求范围 JSP ;这将确保对象不会在有效性过期后仍然存在。默认的,所有的表单都被保存为会话范围。会话中表单对象脱离有效性的存在可能导致浪费内存,同样的,请求处理器必须跟踪保存在会话中的表单对象的生命周期。一个好的捕获表单数据的实践是为横跨多用户交互的相关表单用一个单独的表单 bean 。表单 bean 也可以在反馈的时候用来储存能够被自定义标签改变的中间模型状态。在视图中标签用法避免结合 Java 代码,因此要成一个好的任务划分, web 生产组主要处理标志,而应用开发组主要处理 Java 代码。标签因素退出访问中间模型状态的逻辑;当访问嵌套的对象或当通过聚集列举时这个逻辑可能很复杂。

注意:在 struts1.1 中, ActionForm 的校验功能,逐渐被剥离出来(当然依然可以使用)。使用了 validator framework 对整个应用系统的表单数据验证进行统一管理。相信信息请参考: http://home.earthlink.net/~dwinterfeldt

ActionForm 的使用中, Struts 提倡使用到值对象( Value Object )。这样将客户或开发人员,对数据状态与对象状态能够更加清晰的理解和使用。

对于每一个客户请求, Struts framework 在处理 ActionForm 的时候,一般需要经历如下几个步骤:

(1)检查 Action 的映射,确定 Action 中已经配置了对 ActionForm 的映射

       (2)根据 name 属性,查找 form bean 的配置信息

       (3)检查 Action formbean 的使用范围,确定在此范围下,是否已经有此 form bean 的实例。

       (4)假如当前范围下,已经存在了此 form bean 的实例,而是对当前请求来说,是同一种类型的话,那么就重用。

       (5)否则,就重新构建一个 form bean 的实例

       (6) form bean reset() 方法备调用

       (7)调用对应的 setter 方法,对状态属性赋值

       (8)如果 validatede 的属性北设置为 true ,那么就调用 form bean validate() 方法。

9 )如果 validate ()方法没有返回任何错误,控制器将 ActionForm 作为参数,传给 Action 实例的 execute ()方法并执行。

 

注意:直接从 ActionFrom 类继承的 reset() validate() 方法,并不能实现什么处理功能,所以有必要自己重新覆盖。

Struts 的其他组件

       Struts framework 本身提供了很多可扩展的组件或 sub framework ,方便的开发人员在其构架上构建 web 层的应用系统。比如 upload,collections ,logging 等等。让我们来看看两个比较重要的组件: validationg framework struts taglib 。有关其他组件请参考 Struts 用户手册( http://jakarta.apache.org/struts/userGuide )。

      

Validation Framework for Struts

struts1.1 中,新增了 validation framework 。增加了对 form 数据提交的验证。将原本需要在 ActionFrom Bean validate ()进行的验证通过配置文件的描述进行验证。

有关其详细信息,请参考 http://home.earthlink.net/~dwinterfeldt 。个人建议对于小型应用系统可以采用这种配置方式,但是对于应用系统中有大量 web 层表单应用的系统,并且业务需求变动比较大的,使用 validation framework 可能会加重开发难度、系统维护难度。可以借鉴 validation framework Javascript Validator Tag

 

Struts TagLib

       struts 提供了一组可扩展的自定义标签库( TagLib ),可以简化创建用户界面的过程。目前包括: Bean Tags HTML Tags Logic Tags Nested Tags Template Tags  这几个 Taglib 。有关 Struts Taglib 的结构和使用,可以参考前面有关 Cutomer Tag Lib 的介绍,有关起详细资料,请参考

BeanUtils

       这个组件的全称是 Bean Introspection Utilites 。是属于 Jakarta Commons 项目组的。主要是帮助构建 javabean 的属性操作的( getter,setter ),已经提供一种动态定义和访问 bean 的属性。有关详细信息,请参考。

http://jakarta.apache.org/commons/beanutils.html

       如果各位对这方面有很兴趣,可以参考一些有关 java 反射( Reflectio )方面的资料。

Collections

       这个组件主要是提供了一些集合或列表对象 在原有的 java collections framework 的基础上进行了扩展。详细资料请参考:

http://jakarta.apache.org/commons/collections.html 以及

http://cvs.apache.org/viewcvs/~checkout~/jakarta-commons/collections/STATUS.html?rev=1.13

Digester

       这个组件翻译成中文的意思是 汇编 。其主要功能是根据 xml 配置文件,初始化系统的一些 java 类对象。 Digester 帮助你指定 XML java 对象之间映射模型,而且允许客户话定制映射规则( rules )。详细资料请参考

http://jakarta.apache.org/commons/digester.html

 

 



Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=323752

posted on 2006-12-20 16:07 芦苇 阅读(598) 评论(0)  编辑  收藏 所属分类: Struts

只有注册用户登录后才能发表评论。


网站导航: