struts2拦截器的实现机制

Posted java农民工

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了struts2拦截器的实现机制相关的知识,希望对你有一定的参考价值。

前言

最近老大让每周写一篇技术性的博客,想想也没啥写,就想着随便拿个以前的项目去研究研究五大框架的底层代码。本人水平有限,有不对的地方还望大家勿喷,指正!
开始之前先了解下strtus2的工作流程:

工作原理图:
struts2工作原理图
(1) 客户端(Client)向Action发用一个请求(Request)
(2) Container通过web.xml映射请求,并获得控制器(Controller)的名字
(3) 容器(Container)调用控制器(StrutsPrepareAndExecuteFilter或FilterDispatcher)。在Struts2.1以前调用FilterDispatcher,Struts2.1以后调用StrutsPrepareAndExecuteFilter
(4) 控制器(Controller)通过ActionMapper获得Action的信息
(5) 控制器(Controller)调用ActionProxy
(6) ActionProxy读取struts.xml文件获取action和interceptor stack的信息。
(7) ActionProxy把request请求传递给ActionInvocation
(8) ActionInvocation依次调用action和interceptor
(9) 根据action的配置信息,产生result
(10) Result信息返回给ActionInvocation
(11) 产生一个HttpServletResponse响应
(12) 产生的响应行为发送给客服端。

拦截器所涉及的接口和类:

用struts2实现拦截器有三种方式:

   1.实现Interceptor接口

	public interface Interceptor
    extends Serializable
    //继承Serializable
{
    public abstract void destroy();
    public abstract void init();
    //ActionInvocation 是一个接口
    public abstract String intercept(ActionInvocation actioninvocation)
        throws Exception;
}

2.继承AbstractInterceptor类

	public abstract class AbstractInterceptor
    implements Interceptor
    //并没有具体实现
{
  public AbstractInterceptor()
    {
    }
    public void init()
    {
    }
    public void destroy()
    {
    }
    public abstract String intercept(ActionInvocation actioninvocation)
        throws Exception;
}

所以我们并不建议用上面那两种方法

  1. 继承MethodFilterInterceptor类
       public abstract class MethodFilterInterceptor extends AbstractInterceptor
    {
        public MethodFilterInterceptor()
        {
            log = LoggerFactory.getLogger(getClass());
            excludeMethods = Collections.emptySet();
            includeMethods = Collections.emptySet();
        }
        public void setExcludeMethods(String excludeMethods)
        {
            this.excludeMethods = TextParseUtil.commaDelimitedStringToSet(excludeMethods);
        }
        public Set getExcludeMethodsSet()
        {
            return excludeMethods;
        }
        public void setIncludeMethods(String includeMethods)
        {
            this.includeMethods = TextParseUtil.commaDelimitedStringToSet(includeMethods);
        }
        public Set getIncludeMethodsSet()
        {
            return includeMethods;
        }
        public String intercept(ActionInvocation invocation)
            throws Exception
        {
            if(applyInterceptor(invocation))
                return doIntercept(invocation);
            else
                return invocation.invoke();
        }
       protected boolean applyInterceptor(ActionInvocation invocation)
        {
           //ActionInvocation将Web页面中的输入元素封装为一个(请求)数据对象”,这个对象就是ActionInvocation类型.
            String method = invocation.getProxy().getMethod();
            boolean applyMethod = MethodFilterInterceptorUtil.applyMethod(excludeMethods, includeMethods, method);
            if(log.isDebugEnabled() && !applyMethod)
                log.debug((new StringBuilder()).append("Skipping Interceptor... Method [").append(method).append("] found in exclude list.").toString(), new String[0]);
            return applyMethod;
        }
        protected abstract String doIntercept(ActionInvocation actioninvocation)
            throws Exception;
        protected transient Logger log;
        //排除的方法集合
        protected Set excludeMethods;
        //包括的方法集合(就是要拦截的方法)
        protected Set includeMethods;
    }

如上图:
在执行Action的前后都有拦截器的执行,每个拦截器类的doIntercept(ActionInvocation actionInvocation)方法都会传入一个参数ActionInvocation actionInvocation并且最后一句代码都是return invocation.invoke(),这句代码调用的是DefaultActionInvocation类的invoke方法,而在这个方法里面又会去调用其他的拦截器,这样的话就形成了一个类似递归的递归调用。


上面的这两张图说明了用拦截器时配置文件的基本配法。
下面用debug的方式跟下代码:

总结

Struts2拦截器执行机理如下:

  1. 整个结构就如同一个堆栈,除了Action以外,堆栈中的其他元素是Interceptor

  2. Action位于堆栈的底部。由于堆栈"先进后出"的特性,如果我们试图把Action拿出来执行,我们必须首先把位于Action上端的Interceptor拿出来执行。这样,整个执行就形成了一个递归调用

  3. 每个位于堆栈中的Interceptor,除了需要完成它自身的逻辑,还需要完成一个特殊的执行职责。这个执行职责有3种选择:

  1. 中止整个执行,直接返回一个字符串作为resultCode

  2. 通过递归调用负责调用堆栈中下一个Interceptor的执行

  3. 如果在堆栈内已经不存在任何的Interceptor,调用Action

以上是关于struts2拦截器的实现机制的主要内容,如果未能解决你的问题,请参考以下文章

浅谈Struts2拦截器的原理与实现

详解Struts2拦截器机制与自定义拦截器

struts2 的自定义 拦截器

Struts2-整理笔记拦截器拦截器配置

Struts2 06--系统拦截器防止数据重复提交

struts2异常处理机制