• 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

  • 相关阅读:
    centos7 安装RabbitMQ
    idea 好用的java插件
    eureka 创建服务注册中心
    服务治理 1.注册中心知多少
    服务治理组件比较
    springboot 引入 fastDFS
    centos7 安装 fastDFS
    2、常用查询
    1-库表查看及常用数据类型
    报错:is not allowed to connect tothis mmysql server(mysql无法链接外网)
  • 原文地址:https://www.cnblogs.com/nnxud/p/8998008.html
Copyright © 2020-2023  润新知