• struts2学习笔记(六)—— 拦截器


    一、拦截器概述

      拦截器,在AOP(Aspect-Oriented Programming)中用于在某个方法或字段被访问之前进行拦截,然后在之前或之后加入某些操作。拦截器是AOP的一种实现策略。

      在Webwork的中文文档的解释为:拦截器是动态拦截Action调用的对象。它提供了一种机制可以使开发者可以定义在一个action执行的前后执行的代码,也可以在一个action执行前阻止其执行。同时也是提供了一种可以提取action中可重用的部分的方式。

      谈到拦截器,还有一个词大家应该知道——拦截器链(Interceptor Chain,在Struts 2中称为拦截器栈Interceptor Stack)。拦截器链就是将拦截器按一定的顺序联结成一条链。在访问被拦截的方法或字段时,拦截器链中的拦截器就会按其之前定义的顺序被调用。

    二、拦截器的实现原理

      大部分时候,拦截器方法都是通过代理的方式来调用的。Struts2的拦截器实现相对简单。当请求到达Struts 2的ServletDispatcher时,Struts 2会查找配置文件,并根据其配置实例化相对的拦截器对象,然后串成一个列表(list),最后一个一个地调用列表中的拦截器。事实上,我们之所以能够如此灵活地使用拦截器,完全归功于“动态代理”的使用。动态代理是代理对象根据客户的需求做出不同的处理。对于客户来说,只要知道一个代理对象就行了。那Struts2中,拦截器是如何通过动态代理被调用的呢? 当Action请求到来的时候,会由系统的代理生成一个Action的代理对象,由这个代理对象调用Action的execute()或指定的方法,并在 struts.xml中查找与该Action对应的拦截器。如果有对应的拦截器,就在Action的方法执行前(后)调用这些拦截器;如果没有对应的拦截 器则执行Action的方法。其中系统对于拦截器的调用,是通过ActionInvocation来实现的。

      Struts2拦截器是可插拔的,拦截器是AOP的一种实现。Struts2拦截器栈就是将拦截器按一定的顺序联结成一条链。在访问被拦截的方法或字段时,Struts2拦截器链中的拦截器就会按其之前定义的顺序被调用。

    三、自定义拦截器

    3.1 实现Interceptor接口

    public class MyInterceptor implements Interceptor {
    
        @Override
        // 初始化方法
        public void init() {
        }
    
        @Override
        // 拦截方法
        public String intercept(ActionInvocation arg0) throws Exception {
            return null;
        }
        
        @Override
        // 销毁方法
        public void destroy() {
        }
    }

      Interceptor接口提供了三个方法,其具体介绍如下

    • void init():该方法在拦截器被创建后会立即调用,它在拦截器的生命周期内只被调用一次,可以在该方法中对相关资源进行必要的初始化。
    • void destroy():该方法与init方法相对应,在拦截器实例被销毁之前,将调用该方法来释放和拦截器相关的资源。它在拦截器的生命周期内也只被调用一次。
    • String interceptor(ActionInvocation invocation):该方法是拦截器的核心方法,用来添加真正执行拦截工作的代码,实现具体的拦截操作。它返回一个字符串作为逻辑视图,系统根据返回的字符串跳转到对应的视图资源。每拦截一个动作请求, 该方法就会被调用一次。该方法的ActionInvocation参数包含了被拦截的Action的引用,可以通过该参数的invoke()方法,将控制权转给下一个拦截器或者转给Action的execute()方法。

    3.2 继承AbstractInterceptor

    // 帮我们空实现了init和destory方法,如果我们不需要实现这两个方法,就可以只实现intercept方法
    public class MyInterceptor extends AbstractInterceptor{
    
        @Override
        public String intercept(ActionInvocation arg0) throws Exception {
            return null;
        }
    }

      抽象类AbstractInterceptor已经实现了Interceptor接口的所有方法,一般情况下,只需继承AbstractInterceptor类,实现interceptor()方法就可以创建自定义拦截器。
      只有当自定义的拦截器需要打开系统资源时,才需要覆盖AbstractInterceptor类的init()方法和destroy()方法。与实现Interceptor接口相比,继承AbstractInterceptor类的方法更为简单

    3.3 继承MethodFilterInterceptor

    // 功能:定制拦截器拦截的方法
    // 定制哪些方法需要拦截,哪些方法不需要拦截
    public class MyInterceptor extends MethodFilterInterceptor{
    
        @Override
        protected String doIntercept(ActionInvocation invocation) throws Exception {
            // 前处理
            System.out.println("MyInterceptor的前处理");
            // 放行
            String result = invocation.invoke();
            // 后处理
            System.out.println("MyInterceptor的后处理");
            return result;
            // 不放行,直接跳转到一个结果页面(不执行后续的拦截器以及Action,直接交给Result处理结果.进行页面跳转)
            // return "success";
        }
    
    }

      MethodFilterInterceptor是AbstractInterceptor的子类,该类中提供了两个属性,可以告知拦截器对哪些方法进行拦截或者对哪些方法排除。这种方法在开发中最常用

      

    四、配置拦截器

    <package name="interceptor" namespace="/" extends="struts-default">
        <interceptors>
            <!-- 1.注册拦截器 -->
            <interceptor name="myInterceptor" class="cn.itcast.interceptor.MyInterceptor"></interceptor>
            <!-- 2.注册拦截器栈 -->
            <interceptor-stack name="myStack">
                <!-- 引入自定义拦截器(建议放在20个拦截器之前) -->
                <interceptor-ref name="myInterceptor">
                    <!-- 指定哪些方法不拦截 
                    <param name="excludeMethods">add,delete</param> -->
                    <!-- 指定哪些方法要拦截 -->
                    <param name="includeMethods">add,delete</param>
                </interceptor-ref>
                <!-- 引入默认的拦截器栈(20个) -->
                <interceptor-ref name="defaultStack"></interceptor-ref>
            </interceptor-stack>
        </interceptors>
        <!-- 3.指定包中的默认拦截器栈 -->
        <default-interceptor-ref name="myStack"></default-interceptor-ref>
        
        <action name="Demo1Action_*" class="cn.itcast.action.Demo1Action" method="{1}">
            <result name="success" type="dispatcher">/index.jsp</result>
        </action>
    </package>
  • 相关阅读:
    第14章 位图和位块传输_14.1-14.3 位图基础
    第13章 使用打印机_13.2 打印图形和文字
    第13章 使用打印机_13.1 打印基础
    第12章 剪贴板_12.3 实现一个剪贴板查看器
    第12章 剪贴板_12.2 剪贴板的高级用法
    第12章 剪贴板_12.1 剪贴板的简单用法
    第11章 对话框_11.3 通用对话框
    第11章 对话框_11.2 非模态对话框
    第11章 对话框_11.1 模态对话框
    第5章 作业和进程池(2)
  • 原文地址:https://www.cnblogs.com/yft-javaNotes/p/10277636.html
Copyright © 2020-2023  润新知