posts - 431,  comments - 344,  trackbacks - 0
WebWork 教程 - Interceptor( 拦截器 )
Interceptor (拦截器)将 Action 共用的行为独立出来,在 Action 执行前后运行。这也就是我们所说的 AOP Aspect Oriented Programming ,面向切面编程),它是分散关注的编程方法,它将通用需求功能从不相关类之中分离出来;同时,能够使得很多类共享一个行为,一旦行为发生变化,不必修改很多类,只要修改这个行为就可以。
 
Interceptor 将很多功能从我们的 Action 中独立出来,大量减少了我们 Action 的代码,独立出来的行为具有很好的重用性。 XWork WebWork 的许多功能都是有 Interceptor 实现,可以在配置文件中组装 Action 用到的 Interceptor ,它会按照你指定的顺序,在 Action 执行前后运行。 Interceptor 在框架中的应用如下图所示
 
 
当你提交对 Aciton (默认是 .action 结尾的 Url )的请求时, ServletDispatcher 会根据你的请求,去调度并执行相应的 Action 。在 Action 执行之前,调用被 Interceptor 截取, Interceptor Action 执行前后运行。
 
我们在用户注册的例子中就使用了取得 Request 请求参数的拦截器,配置文件中 <interceptor-ref name="params"/> 将拦截器 params 组装到 RegisterAction 中。“ params ”在我们的 webwork-default.xml 配置文件中有定义, webwork-default.xml 中拦截器的定义如下:
 
<interceptors>
            <interceptor name="timer" class="com.opensymphony.xwork.interceptor.TimerInterceptor"/>
            <interceptor name="logger" class="com.opensymphony.xwork.interceptor.LoggingInterceptor"/>
            <interceptor name="chain" class="com.opensymphony.xwork.interceptor.ChainingInterceptor"/>
            <interceptor name="static-params" class="com.opensymphony.xwork.interceptor.StaticParametersInterceptor"/>
            <interceptor name="params" class="com.opensymphony.xwork.interceptor.ParametersInterceptor"/>
            <interceptor name="model-driven" class="com.opensymphony.xwork.interceptor.ModelDrivenInterceptor"/>
            <interceptor name="component" class="com.opensymphony.xwork.interceptor.component.ComponentInterceptor"/>
            <interceptor name="token" class="com.opensymphony.webwork.interceptor.TokenInterceptor"/>
            <interceptor name="token-session" class="com.opensymphony.webwork.interceptor.TokenSessionStoreInterceptor"/>
            <interceptor name="validation" class="com.opensymphony.xwork.validator.ValidationInterceptor"/>
            <interceptor name="workflow" class="com.opensymphony.xwork.interceptor.DefaultWorkflowInterceptor"/>
            <interceptor name="servlet-config" class="com.opensymphony.webwork.interceptor.ServletConfigInterceptor"/>
            <interceptor name="prepare" class="com.opensymphony.xwork.interceptor.PrepareInterceptor"/>
            <interceptor name="conversionError" class="com.opensymphony.webwork.interceptor.WebWorkConversionErrorInterceptor"/>
            <interceptor-stack name="defaultStack">
                <interceptor-ref name="static-params"/>
                <interceptor-ref name="params"/>
                <interceptor-ref name="conversionError"/>
            </interceptor-stack>
            <interceptor-stack name="validationWorkflowStack">
                <interceptor-ref name="defaultStack"/>
                <interceptor-ref name="validation"/>
                <interceptor-ref name="workflow"/>
            </interceptor-stack>
        </interceptors>
这些都时有框架提供的默认的 Interceptor ,下面我来看看 Interceptor 使用的步骤:
1、   创建一个自己需要的 Interceptor 类,它必需实现
com.opensymphony.xwork.interceptor.Interceptor
接口,具体的开发见下面的 Interceptor 的原理。
2、   在配置文件( xwork..xml )中申明这个 Interceptor 类,它放在标签 <interceptor /> 中,同是 <interceptor /> 标签嵌入在 <interceptors /> 标签内部。
3、   创建 Interceptor 栈,使用标签: <interceptor-stack /> 让一组 Interceptor 可以按次序调用。(可选)
4、   指定 Action 所要用到的 Interceptor (前面申明过的),可以用 <interceptor-ref /> <default-interceptor-ref /> 标签。前面的标签指定某个 Action 所用到的 Interceptor ,如果 Action 没有被用 <interceptor-ref /> 指定 Interceptor ,它将使用 <default-interceptor-ref /> 指定的 Interceptor
框架中给我们提供了很多实用的 Interceptor ,它的定义上面已经给出,它的具体功能如下:
l          timer :记录 Action 执行的时间,并做为日志信息输出;
l          logger :在日志信息中输出要执行的 Action 信息;
l          chain :将前一个执行结束的 Action 属性设置到当前的 Action 中。它被用在 ResultType 为“ chain ”指定结果的 Action 中,该结果 Action 对象会从 OgnlValueStack 中获得前一个 Action 对应的属性,它实现 Action 链之间的数据传递;
l          static-params :将 xwork.xml 配置文件里定义的 Action 参数,设置到对应的 Action 中。 Action 参数使用 <param /> 标签,是 <action /> 标签的直接子元素。我们这里定义的 Action 类必需实现 com.opensymphony.xwork.config.entities . Parameterizable 接口;
l          params :将 Request 请求的参数设置到相应 Action 对象的属性中,用户注册例子用到过这个拦截器;
l          model-driven :如果 Action 实现 ModelDriven 接口,它将 getModel() 取得的模型对象存入 OgnlValueStack 中;
l          component :激活组件功能支持,让注册过的组件在当前 Action 中可用,即为 Action 提供 IoC (依赖倒转控制)框架的支持;
l          token :核对当前 Action 请求( request )的有效标识,防止重复提交 Action 请求 (request)
l          token-session :功能同上,但是当提交无效的 Action 请求标识时,它会将请求数据保存到 session 中。
l          validation :实现使用 xml 配置文件( {Action}-validation.xml )对 Action 属性值进行验证,详细请看后面介绍的验证框架。
l          workflow :调用 Action 类的验证功能,假设 Action 使用 ValidationAware 实现验证( ActionSupport 提供此功能),如果验证没有通过, workflow 会将请求返回到 input 视图( Action <result /> 中定义的)。
l          servlet-config :提供 Action 直接对 HttpServletRequest HttpServletResponse JavaServlet api 的访问, Action 要实现相应的接口,例如: ServletRequestAware ServletResponseAware 。如果必需要提供对 JavaServlet api 的访问,我们建议使用 ServletActionContext ,在前面 ActionContext 章节中有介绍。
l          prepare :在 Action 执行之前调用 Action prepare() 方法,这个方法是用来准备 Action 执行之前要做的工作。它要求我们的 Action 必需实现 com.opensymphony.xwork . Preparable 接口
conversionError :用来处理框架进行类型转化 (Type Conversion) 时的出错信息。它将存储在 ActionContext 中的类型转化( Type Conversion )错误信息转化成相应的 Action 字段的错误信息,保存在堆栈中。根据需要,可以将这些错误信息在视图中显示出来。
 
Interceptor 的原理
下面我们来看看 Interceptor 是如何实现在 Action 执行前后调用的:
Action Interceptor 在框架中的执行,是由 ActionInvocation 对象调用的。它是用方法: String invoke() throws Exception; 来实现的,它首先会依次调用 Action 对应的 Interceptor ,执行完成所有的 Interceptor 之后,再去调用 Action 的方法,代码如下:
if (interceptors.hasNext()) {
Interceptor interceptor = (Interceptor) interceptors.next();
resultCode = interceptor.intercept(this);
} else {
     if (proxy.getConfig().getMethodName() == null) {
resultCode = getAction().execute();
} else {
        resultCode = invokeAction(getAction(), proxy.getConfig());
}
}
它会在拦截器栈中遍历 Interceptor ,调用 Interceptor 方法:
String intercept(ActionInvocation invocation) throws Exception;
我们一直都提到, Interceptor 是在 Action 前后执行,可是从上面的代码我们看到的却是执行完所有 Interceptor intercept () 方法之后再去调用我们的 Action 。“在 Action 前后执行”是如何实现的呢?我们来看看抽象类 AroundInterceptor intercept () 实现:
public String intercept(ActionInvocation invocation) throws Exception {
        String result = null;
 
        before(invocation);
        result = invocation.invoke();
        after(invocation, result);
 
        return result;
    }
原来在 intercept () 方法又对 ActionInvocation invoke() 方法进行递归调用, ActionInvocation 循环嵌套在 intercept () 中,一直到语句 result = invocation.invoke(); 执行结束,即: Action 执行完并返回结果 result ,这时 Interceptor 对象会按照刚开始执行的逆向顺序依次执行结束。这样 before () 方法将在 Action 执行前调用, after () 方法在 Action 执行之后运行
posted on 2006-12-14 19:16 周锐 阅读(642) 评论(0)  编辑  收藏 所属分类: Webwork

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


网站导航:
博客园   IT新闻   Chat2DB   C++博客   博问