`

Struts2.0中ActionInvocation使用 (转)

    博客分类:
  • SSH
 
阅读更多

Interceptor说明

Interceptor的接口定义没有什么特别的地方,除了init和destory方法以外,intercept方法是实现整个拦截器机制的核心方法。而它所依赖的参数ActionInvocation则是我们之前章节中曾经提到过的著名的Action调度者。

我在这里需要指出的是一个很重要的方法invocation.invoke()。这是ActionInvocation中的方法,而ActionInvocation是Action调度者,所以这个方法具备以下2层含义(详细看DefaultActionInvocation源代码): 

1. 如果拦截器堆栈中还有其他的Interceptor,那么invocation.invoke()将调用堆栈中下一个Interceptor的执行。 

 

2. 如果拦截器堆栈中只有Action了,那么invocation.invoke()将调用Action执行。

3.



 DefaultActionInvocation部分源代码:

 if (interceptors.hasNext()) {
       final InterceptorMapping interceptor = (InterceptorMapping) interceptors.next();
       UtilTimerStack.profile("interceptor: "+interceptor.getName(), 
         new UtilTimerStack.ProfilingBlock<String>() {
       public String doProfiling() throws Exception {
           resultCode = interceptor.getInterceptor().intercept(DefaultActionInvocation.this);//递归调用拦截器
           return null;
       }
       });
      } else {
       resultCode = invokeActionOnly();
      }

 每个拦截器中的代码的执行顺序,在Action之前,拦截器的执行顺序与堆栈中定义的一致;而在Action和Result之后,拦截器的执行顺序与堆栈中定义的顺序相反。

Interceptor拦截类型 

从上面的分析,我们知道,整个拦截器的核心部分是invocation.invoke()这个函数的调用位置。事实上,我们也正式根据这句代码的调用位置,来进行拦截类型的区分的。在Struts2中,Interceptor的拦截类型,分成以下三类: 

1. before 

before拦截,是指在拦截器中定义的代码,它们存在于invocation.invoke()代码执行之前。这些代码,将依照拦截器定义的顺序,顺序执行。 

2. after 

after拦截,是指在拦截器中定义的代码,它们存在于invocation.invoke()代码执行之后。这些代码,将依照拦截器定义的顺序,逆序执行。

3、 PreResultListener 

有的时候,before拦截和after拦截对我们来说是不够的,因为我们需要在Action执行完之后,但是还没有回到视图层之前,做一些事情。Struts2同样支持这样的拦截,这种拦截方式,是通过在拦截器中注册一个PreResultListener的接口来实现的。

如:在拦截器中使用如下代码,其中MyPreResultListener实现了PreResultListener 接口并在beforeResult方法中做了一些事情然后在拦截器类中加入action.addPreResultListener(new MyPreResultListener());

 从源码中,我们可以看到,我们之前提到的Struts2的Action层的4个不同的层次,在这个方法中都有体现,他们分别是:拦截器(Interceptor)、Action、PreResultListener和Result。在这个方法中,保证了这些层次的有序调用和执行。

问题

使用Struts2作为web框架,知道它的拦截器(Interceptor)机制,类似与Filter和Spring的AOP,于是实现了一个为Action增加自定义前置(before)动作和后置动作(after)的拦截器(曰:WInterceptor),不过用一段时间发现,在WInterceptor的after中,对Action对象的属性修改在页面看不到,对请求对象的属性设置也无效。为什么在调用了Action之后(invokeAction())之后,request就不能使用了呢,拦截器不能改变Action的Result么?

 问题的关键在于,在调用actionInvocation.invoke()的之后,不仅执行类Action,也执行类Result。因而,等退回到拦截器的调用代码时,Result已经生成,View已经确定,这时你再修改模型(Action的属性)或请求对象的属性,对视图不会有任何影响。

 

解决办法:

 方法一:使用现成的PreResultListener监听器事件

 搞清楚原因,卷起袖子干吧,只要让WInterpretor的after事件,放在Result的生成之前就行了。

 

看看XWork的拦截器接口注入的actionInvocation,其实就提供增加Result执行的前置监听事件-PreResultListener:

 

/**  
 * Register a {@link PreResultListener} to be notified after the Action is executed and  
 * before the Result is executed.  
 * <p/>  
 * The ActionInvocation implementation must guarantee that listeners will be called in  
 * the order in which they are registered.  
 * <p/>  
 * Listener registration and execution does not need to be thread-safe.  
 *  
 * @param listener the listener to add.  
 */  
void addPreResultListener(PreResultListener listener);  

因此,让拦截器实现这个接口,就可以自然实现Action执行after事件了。

方法二,实现自己的 ActionInvocation ,手动分离ActionResult的执行

本来前面的方法已经很好了,可是,可是啊,在addPreResultListener里的异常,不会被Struts的框架捕获,而且,addPreResultListener接口不能传递自己的上下文参数,难道动用ThreadLocal传参?

 研究了一下XWork的ActionInvocation 接口默认实现类DefaultActionInvocation, 写了一个包装类,将Action的执行和Result的生成完全分开,或许有人用的着,放上来,见附件(ActionInvocationWrapper),如有不妥之处请告知。

 exeucteAction是执行Action,executeResult是执行Result

 转载地址:http://www.cnblogs.com/leBeauty/archive/2012/09/27/2705932.html

  • 大小: 40.5 KB
分享到:
评论

相关推荐

    Struts2的工作原理和流程

    1 客户端初始化一个指向Servlet容器的请求; 2 这个请求经过一系列的过滤器(Filter)(这些过滤器中有一个叫做...在表示的过程中可以使用Struts2 框架中继承的标签。在这个过程中需要涉及到ActionMapper

    struts2流程与流程图

     一旦Action执行完毕,ActionInvocation负责根据struts.xml中的配置找到对应的返回结果result。 Struts 2的核心控制器是FilterDispatcher,有3个重要的方法:destroy()、doFilter()和Init(),可以在Struts 2的下载...

    Struts2 in action中文版

    9.1 为什么在Struts 2中使用Spring 196 9.1.1 依赖注入能做些什么 197 9.1.2 Spring如何管理对象和注入依赖 199 9.1.3 使用接口隐藏实现 200 9.2 将Spring添加到Struts 2 202 9.2.1 让Spring管理动作、拦截器和结果...

    struts2开发文档

    8 一旦Action执行完毕,ActionInvocation负责根据struts.xml中的配置找 到对应的返回结果。返回结果通常是(但不总是,也可 能是另外的一个Action 链)一个需要被表示的JSP或者FreeMarker的模版。在表示的过程中可以...

    Struts拦截器及token拦截器防止重复提交例子源码

    其中,init和destroy方法会在程序开始和结束时各执行一遍,不管使用了该拦截器与否,只要在struts.xml中声明了该Struts2拦截器就会被执行。 intercept方法就是拦截的主体了,每次拦截器生效时都会执行其中的逻辑。

    ActionInvocation 源码阅读

    AOP 博文链接:https://cuillgln.iteye.com/blog/1705622

    struts2拦截器

    &lt;package name="mySturtsInterceptor" extends="struts-default"&gt; &lt;interceptor name="MyInterceptor" class="com.cn.system.interceptor.MyInterceptor"&gt;&lt;/interceptor&gt; ...

Global site tag (gtag.js) - Google Analytics