Struts 笔记

Struts 概述

随着MVC 模式的广泛使用,催生了MVC 框架的产生。在所有的MVC 框架中,出现最早,应用最广的就是Struts 框架。

Struts 的起源

Struts 是Apache 软件基金组织Jakarta 项目的一个子项目, Struts 的前身是CraigR. McClanahan 编写的JSP Model2 架构。

Struts 在英文中是"支架、支撑"的意思,这表明了Struts 在Web 应用开发中的巨大作用,采用Struts 可以更好地遵循MVC 模式。此外, Struts 提供了一套完备的规范,以基础类库,可以充分利用JSP/Servlet 的优点,减轻程序员的工作量,具有很强的可扩展性。

Struts优点

提高开发效率,减轻了程序员的工作量,降低了重复代码(降低代码冗余),文件不再臃肿。

可以规范软件开发的行为。ActionForm为我们封装请求数据

增加代码的扩展性、移植性

提高代码的可重用性、可读性,无需多个Servlet多个方法

Action转发页面只须配置跳转资源即可,无效全路径、硬编码。降低代码的耦合性

Struts 架构的工作原理

1. Model 部分

Struts 的Model 部分由ActionForm和JavaBean 组成。其中ActionForm用于封装用户请求参数,所有的用户请求参数由系统自动封装成ActionForm 对象:该对象被ActionServlet转发给Action; 然后Action 根据ActionForm里的请求参数处理用户请求。JavaBean 则封装了底层的业务逻辑,包括数据库访问等。在更复杂的应用中,JavaBean所代表的绝非一个简单的JavaBean,可能是EJB 组件或者其他的业务逻辑组件。该Model 对应图3 .4的Model 部分。

2. View 部分

Struts 的View 部分采用JSP 实现。Struts 提供了丰富的标签库,通过这些标签库可以最大限度地减少脚本的使用。这些自定义的标签库可以实现与Model 的有效交互,并增加了显示功能。对应图的JSP 部分。

整个应用由客户端请求驱动,当客户端请求被ActionServlet 拦截时, ActionServlet根据请求决定是否需要调用Model 处理用户请求,当用户请求处理完成后,其处理结果通过JSP 呈现给用户。

3. Controller部分

Struts 的Controller 由两个部分组成。

·系统核心控制器—拦截用户请求ActionServlet 派发请求

·业务逻辑控制器—处理用户请求的Action,处理业务逻辑

其中,系统核心控制器是一个ActionServlet。该控制器由Struts 框架提供,继承HttpServlet类,因此可以配置成一个标准的Servlet。该控制器负责拦截所有Http请求,然后根据用户请求决定是否需要调用业务逻辑控制器,如果需要调用业务逻辑控制器,则将请求转发给Action 处理,否则直接转向请求的JSP 页面。业务逻辑控制器负责处理用户请求,但业务逻辑控制器本身并不具有处理能力,而是调用Model 来完成处理。业务逻辑控制器对应图3 .4中的Action 部分。

clip_image002

下面结合图3.7 对Struts 的工作流程作详细的讲解。

Web 应用都是请求一响应的程序结构。程序是由客户端Client 发出Http 请求开始的,客户端请求被ActionServlet 拦截。在ActionServlet 处,有两种情况:

·要求逻辑控制器处理的请求:

·简单转发的请求。

对于第一种的请求,ActionServlet 需要调用对应的Action。因此ActionServlet 将请求转发到Action ,如果请求还配置了对应的FormBean,则ActionServlet 还负责用请求参数填充ActionForm,此时如果ActionForm还没有创建。ActionServlet会帮我们创建一个可以用的ActionForm,如果ActionForm已经创建就直接给我们用, ActionForm 的实质就是JavaBean,专门用于封装请求参数。并且在次期间,如果ActionForm如果有验证方法,会去执行验证方法,如果验证通过会进入Action中。验证失败,会跳转到Action配置的input资源页面。

此时的Action 将无须从HTTP Request 中获取请求参数,而是从ActionForm 中获得请求参数。Action 获得请求参数后,调用Model 对象由JavaBean 处理用户请求。Action处理完用户请求之后,将处理结果包装成ActionForward,回送给ActionServlet。

由于ActionForward 对象封装了JSP 资源的映射。因此, ActionServlet 知道调用合适的JSP 资源表现给客户端。

对于第二种请求, HTTP 请求无须Action 处理,只是对普通资源的请求,作为超级链接的替代。因为ActionServlet 直接将该请求转发给JSP 资源,既不会填充ActionForm,也无须调用Action 处理。

JSP 页面在表现之前,还需要调用对应的JavaBean,此处的JavaBean 不再是包含业务逻辑的JavaBean,而是封装了处理结果的普通vo (值对象)。JSP 页面根据vo 的值,可能利用JSTL 或者Struts 的标签库来生成HTTP 响应给客户端。总之JSP 应尽量避免使用Java 脚本。

Action配置

path是我们请求访问的路径,如果用struts标签,会默认加上.do的后缀。ActionServlet拦截到*.do的请求后,就进行相应的业务处理,然后派发到path对应的Action;

name是Action对象的ActionForm,ActionForm是封装请求的信息,如表单

attribute和name一样,可以省略,在省略的情况下用name。都是对应ActionForm

type是Action对象对应的文件路径,含包名

scope是ActionForm的作用域,默认request

parameter后带方法名称,即请求所执行的方法

forward是转发后的资源页面

ActionForward配置

name逻辑名称和Action中的mapping.forward参数对应

path对应映射的JSP页面

redirect是否重定向请求

forward有全局和局部的2种,如果当前Action配置的forward资源在当前配置的Action中没有找到,然后回到全局的forward资源中查找。局部优先全局

ActonForm配置

name是form的名称

type是form的包名+文件名

ActionForm还有动态ActionForm、验证ActionForm

国际化I18N(Internationalization

目的:是适应更多的、更好的用户界面

Java 程序的国际化主要通过如下三个类完成。

   java.util. ResourceBundle: 对应用于加载一个资源包。

   java.util.Locale: 对应一个特定的国家/区域及语言环境。

   java.text.MessageFormat: 用于将消息格式化。

为了实现程序的国际化,必须先提供程序所需要的资源文件。资源文件的内容是和很多key-value 对。其中key 是程序使用的部分,而value 则是程序界面的显示。

资源文件的命名可以有如下三种形式。

   baseName _language_country.properties。

   baseName _language.properties。

   baseNarne.properties 。

其中baseName 是资源文件的基本名,用户可以自由定义。而language 和count可都不可随意变化,必须是Java 所支持的语言和国家。

1.国际化支持的语言和国家

事实上, Java 也不可能支持所有国家和语言,如需要获取Java 所支持的语言和国家,可调用Locale 类的getAvailableLocale 方法来获取。该方法返回一个Locale 数组,该数组里包含了Java 所支持的语言和国家。

2. 编写国际化所需的资源

国际化所需的资源文件内容是key-value 对,下面提供了两个资源文件,这两个资源文件很简单,只包含一个key-value 对。

下面是MyResource.properties 的文件的内容:

资源文件的内容: key-value 对。

msg=Hello , {O} Today is {1}.

下面是MyResource_zh_CN.properties 文件的内容:

资源文件的内容: key-value 对

msg=你好. {O} 今天是{l}。

所有资源文件的key 都是相同的,只是value 会随国家和语言的不同而变化。

3.程序从哪里获取资源呢?

在ResourceBundle 加载资源时按如下顺序搜索。

搜索所有国家和语言都匹配的资源文件,例如,对于简体中文的环境,先搜索如下文件:

MyResource_zh_CN.properties

如果没有找到国家和语言都匹配的资源文件,则再搜索语言匹配的文件,即搜索如下文件:

MyResource_zh.properties

如果上面的文件依然无法搜索到,则搜索baseNarne 匹配的文件,即搜索如下文件:

MyResource.properties

4. 使用类文件代替资源文件

Java 也允许使用类文件代替资源文件,即将所有的key-value对存入class 文件,而不是属性文件。

用来代替资源文件的Java 文件必须满足如下条件。

·类的名字必须为baseNarne_language_country,这与属性文件的命名相似。

·该类必须继承ListResourceBundle,并重写getContents 方法,该方法返回Object数组,该数组的每一个项都是key=value 对。

eg:下面的类文件可以代替上面的属性文件:

public class MyResource_zh_CN extends ListResourceBundle {

    // 定义资源

    private final Object myData[][] = { "msg" , " {0}您好!今天是{l} "};

    //重写方法getContents()

    public Object[] [] getContents() {

        //该方法返回资源的key-value对

        return myData;

    }

}

如果系统同时存在资源文件及类文件,则系统将以类文件为主,而不会调用资源文件。对于简体中文的Locale, ResourceBundle 搜索资源的顺序是:

(1) baseName zh CN.class 。

(2) baseNarne_zh_CN.properties。

(3) baseNarne zh.class 。

(4) baseNarne_zh.properties。

(5) baseNarne.class。

(6) baseNarne.properties。

当系统按上面的顺序搜索资源文件时,如果前面的文件不存在,则会使用下一个:如果一直找不到对应的文件,系统将抛出异常。

struts加载资源文件

资源文件的加载通过struts-config.xml文件来配置,加载资源文件应从Web 应用的WEB-INF/classes路径开始加载。因此,资源文件必须放在WEB-INF/classes路径或该路径的子路径下。如果直接放在WEB-INF/classes 路径下,在配置资源文件时,直接指定资源文件的baseName 即可。但如果放在子路径下,则必须以包的形式配置。

动态ActionForm

Why当一个form表单的属性、字段非常多的情况下,需要我们不断的修改、添加ActionForm中的属性,并提供getter、setter方法。虽然这个类比较简单,但是大量重复的getter、setter方法也是比较繁琐的。这个时候struts的动态ActionForm就派上用场了。使用动态ActionForm 的目的是为了减少代码的书写量,但是相对在配置方面要复杂些。

配置动态ActionForm

所有的动态ActionForm 的实现类都必须是org.apache.struts.action.DynaActionForm类,或者是它的子类。使用动态ActionForm 与前面不同的是:因为系统不清楚动态ActionForm 的属性,所以必须在配置文件中配置对应的属性。可以使用form-property 元素来配置动态ActionForm 的属性。

<!一配置动态ActionForm,动态Aciton 必须使用乌rnaActionForm 一〉

<form-bean name="loginForm" type="org.apache.struts.action.DynaActionForm">

     <!一配置ActionForm的属性: username-->

     <form-property name="username" type="java.lang.String"/>

     <! 配置ActionForm的属性: pass-->

     <form-property name="pass"type="java.lang.String"/>

</form-bean>

 

<!-- 配置Action中的path , type , name 属性>

<action path="/login" type="com.hoo.LoginAction" name="loginForm">

     <!一配置两个局部Forward-->

     <forward name="welcome" path="/WEB-INF/jsp/welcome.jsp"/>

     <forward name="input" path="/login.jsp"/>

</action>

从上面的配置文件可看出,动态ActionForm 的配置必须增加form-property 元素,每个属性必须对应一个form-property元素。

form-property元素包含两个属性。

name: 属性的名字,必须与JSP 页面的表单域的名字相同。

type: 属性的类型。

 

使用动态ActionForm

//必须重写该核心方法,该方法actionForm 将表单的请求参数封装成值对象

public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {

     //将ActionForm强制类型转换为DynaActionForm

     DynaActionForm loginForm = (DynaActionForm)form;

     //从ActionForm中解析出请求参数: username

     String username = (String)loginForm.get("username");

     //从ActionForm中解析出请求参数: password

     String pass = (String)loginForm.get("pass");

     //后面的处理与前一个示例的Action 相同。

     …………

}

使用动态ActionForm 时,请求参数必须使用DynaActionForm的getter 方法获取。

DynaActionForm 的getter 方法主要有如下三个。

Object get(java.lang.String name): 根据属性名返回对应的值。

Object get(java.lang.String name, int index): 对于有多个重名表单域的情况, Struts将其当成数组处理,此处根据表面域名和索引获取对应值。

Object get(java.lang.String name, java.lang.String key): 对于使用Map 属性的情况,根据属性名及对应key. 获取对应的值。

 

Struts 的标签库

Struts 提供了大量的标签库,用于完成表现层的输出。借助于Struts 的标签库,可避免在JSP 中嵌入大量的Java 脚本,从而提高代码的可读性。

Struts 主要提供了如下三个标签库。

A、 html: 用于生成HTML 的基本标签。

B、 bean: 用于完成程序国际化,输出Struts 的ActionForm 的属性值等。

C、 logic: 用于完成循环、选择等流程控制。

 

使用html 标签库

Struts 为htrnl 的大部分标签提供了对应的htrnl 标签, htrnl 所支持的标签大致有如下。

* base: 表现成一个HTML 的<base>标签。

* button: 表现成一个按钮,该按钮默认没有任何动作。

* cancel: 表现成一个取消按钮。

* checkbox: 表现成一个Checkbox 的输入框。

* error: 用于输出数据校验的出错提示。

* file: 表现成一个文件浏览输入框。

* form: 表现成一个form 域。

* frame: 表现成一个HTML<frame>标签。

* hidde: 表现成一个隐藏域。

* htrnl: 表现成HTML 的<htrnl>标签。

* image: 表现成表单域的image 域。

* img: 表现成一个HTML 的img 标签。

* javascrit: 表现成JavaScript 的校验代码,这些校验代码根据ValidatorPlugIn 生成。

* link: 表现成HTML 的超级链接。

* messages: 用于输出Struts 的各种提示信息,包括校验提示。

* multibox: 表现成一个Checkbox 输入框。

* option: 表现成选择框的一个选项。

* password: 表现成一个密码输入框。

* radio: 表现成一个单选输入框。

* reset: 表现成一个重设按钮。

* rewrite: 表现成一个URL 。

* select: 表现成一个列表选择框。

* submit: 表现成一个提交按钮。

* text: 表现成一个单行文本输入框。

* textarea: 表现成一个多行文本框。

 

使用bean 标签库

bean 标签库主要用于输出属性值、提示消息及定义请求参数等。下面是bean 标签库的常用标签。

* cookie: 将请求的cookie 的值定义成脚本可以访问的JavaBean 实例。

* define: 将某个bean 的属性值定义成脚本可以访问的变量。

* header: 将请求头的值定义成脚本可以访问的变量。

* include: 将某个JSP 资源完整定义成一个bean 实例。

* message: 用于输出国际化信息。

* page: 将page Context 中的特定项定义成一个bean 。

* parameter: 将请求参数定义成脚本可以访问的变量。

* resource: 加载Web 应用的资源,并将其变成JavaB eano

* struts: 用于将某个Struts 的内部配置成一个bean 。

* write: 用于输出某个bean 的属性值。

 

使用logic 标签库

logic 标签库是使用最频繁,相对复杂的标签库。logic 标签库主要用于完成基本的流程控制,比如循环及选择等。

logic 标签库主要有如下标签。

* empty: 如果给定的变量为空或者为空字符串,则就计算并输出标签体的内容。

* equal: 如果给定变量与特定的值相等,则会计算并输出该标签体的内容。

* forward: 将某个页面的控制权forward 确定的ActionForward 项。

* greaterEqual: 如果给定变量大于或等于特定的值,则会计算并输出标签体的内容。

* greaterThan: 如果给定变量大于特定的值,则会计算井输出标签体的内容。

* iterate: 通过遍历给定集合的元素,对标签体的内容进行循环。

* lessEqual: 如果给定变量小于或等于特定的值,则会计算并输出标签体的内容。

* lessThan: 如果给定变量小于特定的值,则会计算并输出标签体的内容。

* match: 如果特定字符串是给定消息合适的子字符串,则会计算并输出标签体的内容。

* messagesNotPresent: 如果请求中不包含特定的消息内容,将计算并输出标签体的内容。

* messagesPresent: 如果请求中包含特定的消息内容,则计算并输出标签体的内容。

* notEmpty: 如果给定的变量既不为空,也不是空字符串,则计算并输出标签体的内容。

* notEqual: 如果给定变量不等于特定的值,则会计算并输出标签体的内容。

* notMatch: 如果特定宇符串不是给定消息合适的子字符串,则会计算并输出标签体的内容。

* notPresent: 如果特定的值没有出现在请求中,则计算并输出标签体的内容。

* present: 如果特定的值出现在请求中,则计算并输出标签体的内容。

* redirect: 重定向页面。

 

Struts 的数据校验

数据校验也称为输入校验,指导对用户的输入进行基本过滤,包括必填宇段,宇段必须为数字及两次输入的密码必须相匹配等。这些是每个MVC 框架都应该完成的任务,Struts 提供了基本的数据校验,如果结合commons-validator, Struts 则拥有强大的校验框架,包括进行客户端的JavaScript 校验等。

Struts 的数据校验大致有如下几种方式:

ActionForm 的代码校验。

Action 里的代码校验。

结合commons-validator.jar 的校验。

 

ActionForm 的代码校验

ActionForm 的代码校验是最基本的校验方式。这种校验方式是重写ActionForm 的validate 方法,在该方法内对所有的宇段进行基本校验。如果出现不符合要求的输出,则将出错提示封装在ActionError 对象里,最后将多个ActionError 组合成ActionErrors 对象,该对象里封装了全部的出错提示。并将错误信息用<html:error/>展现在配置的input的失败页面上。

 

Action 的代码校验

在Action 里通过代码完成输入校验,是最基本,也最容易使用的方法。与最初的MVC 设计相似,在调用业务逻辑组件之前,先对数据进行基本校验。这是最传统也是最原始的方法。

这种校验方式非常容易理解,所有的代码都需要程序员自己控制,相当灵活。

但有如下几个不方便之处。

·用户需要书写大量的校验代码,使程序变得烦琐。

· 数据校验应该在填充ActionForm里完成,最好能在客户端完成校验,而不是推迟到Action 里才完成数据校验。

注意:在实际的使用中,这种校验方式不仅程序开发复杂,且性能也不高。

 

结合commons-validator.jar 的校验

借助于commons-validator.jar 的支持, Struts的校验功能非常强大,几乎不需书写任何代码。不仅可以完成服务器端校验,同时还可完成客户端校验,即弹出Javascript 提示。

使用commons-validator.jar 校验框架时,有如下几个通用配置。

·增加校验资源。

·利用ValidatorPlugIn 加载校验资源。

·ActionForm 使用ValidatorForm 的于类。

下面分别通过三个示例讲解这三种校验:基本的校验、对动态ActionForm 执行校验及弹出JavaScript 校验提示。

 

1. 继承ValidatorForm 的校验

如果需要使用commons-validator 框架,请按如下步骤进行。

(1) Struts 的ActionForm必须是ValidatorForm的子类,提供验证属性字段的getter、setter方法

(2) 编写表单域时必须满足校验规则。校验规则都由规则文件控制,规则文件有以下两个。

* validator-rules.xml 文件

* validation.xml 文件

第一个文件可在Struts 的解压缩后的文件夹的lib 下找到,将该文件复制到WEB-INF

2. common-validator支持的校验规则

common-validator支持的校验规则非常丰富,特别是mask 和validwhen 两个规则,

极大地丰富了该校验框架的功能。

常用的校验规则有如下几种。

* required: 必填。

* va1idwhen: 必须满足某个有效条件。

* minlength: 输入必须大于最小长度。

* maxlength: 输入必须小于最大长度。

* mask: 输入匹配正确的表达式。

* byte: 输入只能是一个byte 类型变量。

* short: 输入只能是一个short 类型变量。

* integer: 输入只能是一个integer 变量。

* long: 输入只能是一个long 变量。

* float: 输入只能是一个float 变量。

* double: 输入只能是一个double 变量。

* date: 输入必须是一个日期。

* intRange: 输入的数字必须在整数范围内。

* floatRange: 输入的数字必须在单精度浮点数范围内。

* doubleRange: 输入的数字必须在双精度浮点数范围内。

* email: 输入必须是有效的E-mail 地址。

* uri: 输入必须是有效的uri 地址。

3.使用DynaValidatorForm 的校验

即使不书写ActionForm,也可以利用cornmon-validator 校验框架。此时使用的ActionForm 的实现类,必须既是动态Form ,也是验证Form,DynaValidatorForm 就是满足这两个条件的Form。

4. 弹出客户端JavaScript提示

如需要弹出客户端JavaScript 校验非常简单,无须修改其他配置文件,只需修改登录使用的JSP 页面的两个地方。

(1) 为form 元素增加onsubmit="return validateXxxForm(this);"属性,其中的XxxForm就是需要校验的form 名,与struts-config.xrnl中配置的form-bean 的name 属性一致,也与validation.xrnl文件中需要校验的form 的name 属性一致。

(2) 增加<html:javascript formName="xxxForm"/> ,其中xxxForm 是需要校验的form 名。

注意:即使使用了客户端技验规则,也不要删除页面的htm1 :rnessages 标签。因为该标签会在客户端技验通过,而在服务器端技验并未通过时弹出提示。

 

Struts 的异常框架

Struts 1.1 版本中加入了对异常的处理,称之为Exception Handling,标志着作为一个整体的框架, Struts 越来越趋于成熟。

在以前的Struts 开发过程中,对于异常的处理,主要是采用手动处理的方式:如通过try/catch 等捕获异常:然后将定制个性化的,比较详细的错误信息放进ActionMessage中:最后在返回页面中把这些错误信息反馈给用户。

对于异常的原始信息,不管是最终用户还是开发员都不希望看到。

借助于Struts 的异常框架,异常处理只需通过struts-config.xm1文件定义即可。根据异常定义的位置不同,异常可分为局部异常和全局异常两种。

·局部异常作为action 的子元素中定义。

·全局异常在globa1-excetpions 元素中定义。

异常定义的格式如下:

<exception key="keyNarne" type="ExceptionNarne" scope="scope" path="uri"/>: 当Struts 出现ExceptionNarne 的异常时,页面自动转向uri 指向的资源,并在该页面输出keyName 对应的国际化中的出错提示。

几种常用的Action

除了基本的Action 之外, Struts 还提供了几个其他类型的Action ,这些Action 大大丰富了Struts 的功能。下面介绍如下儿个常用的Action 。

* DispatchAction: 能同时完成多个Action 功能的Action 。

* ForwardActon: 该类用来整合Struts 和其他业务逻辑组件,通常只对请求作有效性检查。

* IncludeAction: 用于引入其他的资源和页面。

* LookupDispatchAction: DispatchAction 的子类,根据按钮的key ,控制转发给action的方法。

* MappingDispatchAction: DispatchAction 的子类,一个action 可映射出多个Action地址。

* SwitchAction: 用于从一个模块转换至另一个模块,如果应用分成多个模块时,就可以使用SwitchAction 完成模块之间的切换。

 

DispatchAction

在该action 的配置中,增加了parameter属性,该属性用于指定参数名,即Struts 将根据该参数的值调用对应的方法。为了让请求增加method 的参数,method参数对应的是要请求执行的方法。

<action path="/login" type="com.hoo.LoginAction" name="loginForm" scope="request" validate="true" input="login.jsp" parameter="method">

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

</action>

Login.do?method=login

 

MappingDispatchAction

可将同一个Action 的不同方法映射成多个Action URI ,这种Action 的写法与DispatchAction 非常相似,同样不需要重写execute 方法,而是将书写多个自定义的方法。这些方法除了方法名与execute 方法不同外,其他的参数列表及异常处理完全一样。

<!-- 配置第一个Action. 实现类是com.hoo.LoginAction , parameter 为add-->

<action path="/add" type="com.hoo.LoginAction" name="loginForm" scope="request" validate="true" input="login.jsp" parameter="add">

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

</action>

<! 配置第二个Action. 实现类是com.hoo.LoginAction , parameter 为modify-->

<action path="/modify" type="com.hoo.LoginAction" name="loginForm" scope="request" validate="true" input="login.jsp" parameter="modify">

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

</action>

其中,path对应的是请求的地址uri,而parameter是对于当前请求所执行的方法;

注意:使用MappingDispatchAction 并没有带来太大的优势,系统完全可以书写两个Action,分别定义两个不同的action 映射,而其他部分没有区别。

 

LookupDispatchAction

LookupDispatchAction也是DispatchAction 的一种,但它的处理更加简单。该Action也可包含多个处理方法,它可让处理方法与按钮直接关联,无须使用任何的JavaScript脚本。因此可通过重写getKeyMethodMap方法完成按钮与Action 中方法的关联。

//用于关联按钮和方法

protected Map getKeyMethodMap() {

     Map map = new HashMap();

     //如果按钮标题的key 为button.add. 则提交该按钮时对应add 方法

     map .put ("button. add" , "add");

     //如果按钮标题的key 为button.modify. 则提交该按钮时对应modify 方法

     map.put ("button.modify" , "modify") ;

     return map;

}

 

ForwardAction

如果需要从一个页面或资源转换到另一个资源时,直接使用页面或资源路径的超级链接定位并不是好的做法,这使得控制器没有机会处理相关的请求事直。

使用ForwardAction可以完成请求的转发,当控制器调用ForwardAction的perform()方法时,它会使用属性parameter 所设定的路径进行forward 的动作。下面是一个设定ForwardAction的例子:

<actlon-mapplngs>

     <action path="/welcome" type="org.apache.struts.actions.ForwardAction" parameter="/welcome.jsp"/>

</action-mappings>

该action 仅仅完成转发,并没有执行其他的额外动作。页面控制转发的代码如下:

<a href="welcome.do">转入</a>

当单击转入超级链接时,将可以转向ForwardAction中parameter指向的资源。

 

IncludeAction

IncludeAction的用法与ForwardAction的用法比较相似,区别在于ForwardAction将跳转到action 定义的资源,而IncludeAction用于引入该action 对应的资源。

下面是IncludeAction定义的源代码:

<action-mapplngs>

     <action path="/welcome" type="org.apache. struts.actions.IncludeAction" parameter="/welcome.jsp"/>

</action-mappings>

该action 用于经welcome.jsp 作为资源导入。

页面中负责加载该action 所导入资源的代码如下:

<jsp:include page="welcome.do"/><br>

上面的代码将会把welcome action 定义的资源导入该页面。

 

SwitchAction

SwitchAction 主要用于模块之间的切换。当一个应用之中存在多个模块时,使用SwitchAction在不同模块之间的action 之间切换还是相当方便的。

 

Struts 的常见扩展方法

Struts 的强大吸引力还来自于它的可扩展性,其扩展性通常有如下三种方式。

·实现PlugIn: 如果需要在应用启动或关闭时完成某些操作,可以创建自己的PlugIn类。

·继承RequestProcessor: 如果想在请求被处理中的某个时刻做一些业务逻辑时,可以考虑实现自己的RequestProcessor 类。

·继承ActionServlet: 如果需要在每次开始处理请求之前,或者处理请求结束之后完成某些操作,可以实现自己的ActionServlet 来完成扩展。

 

下面分别从三个方面来介绍Struts 的扩展。

实现PlugIn 接口

Struts 已经演示了PlugIn 的扩展方法:与common- validation 的整合。后面还将介绍Spring 与Struts 的整合,也利用了PlugIn 的扩展。

在下面的应用中,系统使用Hibernate 作为持久层,在启动时创建SessionFactory 实例,并将该SessionFactory 存入application ,在应用关闭时销毁SessionFactory 。只需如下两步即可完成此功能。

(1) 实现自己的PlugIn 类。

     实现PlugIn 接口必须实现如下两个方法。

     1 void destroy()。

     2 void init(ActionServlet serlet, ModuleConfig config) 。

     应用启动时调用init 方法,而应用关闭时则调用destroy 方法。

     下面是SessionFactoryLoaderPlugIn 的实现类:

     public class SessionFactoryLoaderPlugin implements PlugIn {

          //Hibernate 的配置文件

          private String configFile;

          //应用关闭时,销毁资源

          public void destroy()

               System.out.println("系统销毁SessionFactory");

          }

          //应用启动时,完成SessionFactory 的初始化

          public void init(ActionServlet actionServlet , ModuleConfig config) throws ServletException

               System.out.println("系统以" + getConfigFile() + "为配置文件初始化SessionFactory") ;

              //获取Plugln 配置文件的方法

               public String getConfigFile() {

                    return configFile;

               }

          // 负责加载Plugln 配置属性的方法

          public void setConfigFile(String configFile) {

                this.configFile = configFile;

          }

     }

在上面的PlugIn 中,并没有真正初始化SessionFactory ,仅在控制台打印出字符串来标识创建动作。另外,还提供了configFile 属性的setter 和getter 方法,这两个方法负责访问plugin 元素的configFile 属性。

 

( 2 ) 将SessionFactoryLoaderPlugIn 配置在struts-config.xml 文件中。方法与ValidatorPlugIn 的配置并没有区别,下面是配置SessionFactoryLoaderPlugIn 的代码:

<plug-in className="hoo.SessionFactoryLoaderPluging">

     <set-property property="conf工gFile" value=" WEB-INF/hibernate.cfg.xml"I>

</plug-in>

在配置SessionFactoryLoaderPlugIn 时,配置了configFile 属性,该属性用于确定Hibernate 配置文件的文件名。

 

继承RequestProcessor

RequestProcessor 是Struts 的核心类,而Struts 的核心控制器是ActionServlet 。但ActionServlet 并未完成真正的处理,只是调用RequestProcessor , RequestProcessor 才是Struts 的核心类。

扩展RequestProcessor 的实例在Spring 中有个示范, Spring 提供的Delegating RequestProcessor 是一个很好的示例。下面示例对RequestProcessor 进行简单的扩展。

RequestProcessor 包含了如下常见的方法。

* ActionForm processActionForm: RequestProcessor填充ActionForm 时执行该方法。

* Action processActionCreate: RequestProcessor 调用Action 时调用该方法。

* boolean processPreprocess: 预处理用户请求时执行该方法。

* boolean processValidate: 处理输入校验时调用该方法。

扩展RequestProcessor 只需两步即可。

(2)在struts-config.xml 文件中配置MyRequestProcessor。用户重写了RequestProcessor,但Struts 并不知道,必须在struts-config且nl 中配置才可以。

下面是配置MyRequestProcessor 的代码:

<controller processorClass="lee.MyRequestProcessor" />

该属性的配置应该放在action-mappings元素之后。

注意:重写RequestProccessor的方法时,别忘了使用super 来调用父类的动作。如果没有调用该方法,意味着开发者必须完成Struts 框架所完成的动作。这是不应该的,因为程序员只是在框架中加入额外的处理,并不是要替代Struts。

 

继承ActionServlet

如果需要在开始处理请求,或者处理结束之后加入自己的处理时,可对ActionServlet进行扩展。例如解决中文的编码问题。

ActionServlet 接收处理请求参数时,并不是按GBK 的解码方式处理请求,因此容易形成乱码。为了解决该问题,可以强制指定ActionServlet 使用GBK 的解码方式。

继承ActionServlet重写process方法,设置request、response编码为gbk,然后配置在web.xml中。

posted on 2012-01-29 16:44  hoojo  阅读(2720)  评论(0编辑  收藏  举报