zoukankan      html  css  js  c++  java
  • struts2 拦截器和actioninvocation

    一、Interceptor说明

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

      在这里需要指出的是一个很重要的方法invocation.invoke()。这是ActionInvocation中的方法,而ActionInvocation是Action调度者,所以这个方法具备以下2层含义(详细看DefaultActionInvocation源代码): 
      1、 如果拦截器堆栈中还有其他的Interceptor,那么invocation.invoke()将调用堆栈中下一个Interceptor的执行。 
      2、 如果拦截器堆栈中只有Action了,那么invocation.invoke()将调用Action执行。

     流程结构图:

    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拦截类型 

    二、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:

    void addPreResultListener(PreResultListener listener);

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

      方法二:实现自己的 ActionInvocation ,手动分离Action和Result的执行

      本来前面的方法已经很好了,可是在addPreResultListener里的异常,不会被Struts的框架捕获,而且addPreResultListener接口不能传递自己的上下文参数,难道动用ThreadLocal传参?研究了一下XWork的ActionInvocation 接口默认实现类DefaultActionInvocation,可以 写了一个包装类,将Action的执行和Result的生成完全分开。exeucteAction是执行Action,executeResult是执行Result。

    转载于https://blog.csdn.net/xuchuangqi/article/details/53248306

  • 相关阅读:
    linux的lsof命令
    linux find
    linux 查看磁盘空间大小
    eclipse运行时编码设置
    WebService工作原理
    Java获取字符串编码方式
    JavaScript,base64加密解密
    如何用javascript 的eval动态执行一个需要传对象参数的函数
    struts2结果类型
    执行maven-build.cmd失败
  • 原文地址:https://www.cnblogs.com/liuxiaochong/p/13560903.html
Copyright © 2011-2022 走看看