• 拦截器原理(AOP、责任链模式、拦截器的创建、自定义拦截器)


    1、Struts2拦截器概述:

    (1)Struts2框架封装中封装了很多功能,这些功能其实都是封装在Struts2的拦截器里面,Struts2里面有很多拦截器,每次不是这些拦截器都执行,每次只执行默认的拦截器。

    (2)Struts2默认拦截器的位置:

     (3)拦截器在Action对象创建之后,action的方法执行之前执行。

    2、Struts2底层原理:

    (1)原理一(AOP思想):

    AOP:面向切面(方面)编程,不通过修改源代码的方式来扩展功能。

    在上面的登录流程图中,如果在登录成功后要添加用户的权限判断功能,不需要修改源代码。

    (2)责任链模式(和过滤链模式思想相似):

    过滤链模式:一个请求需要经过多个过滤器,而每个过滤器只有经过放行操作后才能进行下一步操作。

    责任链模式:例如执行:添加、删除、修改操作,先执行添加操作,添加操作执行结束之后执行删除操作(类似于过滤链模式中的放行操作),执行删除操作之后执行修改操作。

    3、AOP思想和责任链模式在Struts2中的应用:

    (1)拦截器在Action对象创建之后,action的方法执行之前执行(在Action方法执行之前执行默认拦截器,执行过程中使用AOP思想,在Action中没有直接调用拦截器的方法,而是使用配置文件的方式进行操作)。

    (2)如果拦截器执行过程中有多个拦截器则采用责任链模式进行,如果有三个拦截器,则先执行拦截器一,执行一之后做放行操作,然后执行拦截器二,做放行操作,最后执行拦截器三,放行后,执行Action方法。

    4、过滤器和拦截器的区别:

    (1)过滤器:过滤器理论上可以过滤任何内容,例如:图片、html、jsp、servlet的路径。

    (2)拦截器:拦截器只能拦截Action。

    5、servlet和action的区别:

    (1)servlet:只在首次访问的时候创建,只创建一次(单实例对象)

    (2)action:每次访问的时候创建,可以创建多次(多实例对象)

    6、生命周期:

    随项目的启动而创建,随项目的关闭而销毁。

    7、拦截器的创建方法

    (1)方法一:实现接口(需要实现三个方法,不推荐)

    import com.opensymphony.xwork2.ActionInvocation;
    import com.opensymphony.xwork2.interceptor.Interceptor;
    public class InterceptorDemo implements Interceptor {
        @Override
        public void destroy() {
            
        }
    
        @Override
        public void init() {
    
        }
    
        @Override
        public String intercept(ActionInvocation actionInvocation) throws Exception {
            return null;
        }
    }

    (2)方法二:继承AbstractInterceptor类,因为该类已经实现了Interceptor接口,因此较为方便(帮我们实现了init和destory方法,就可以只实现intercept方法):

    import com.opensymphony.xwork2.ActionInvocation;
    import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
    
    public class InterceptorDemo1 extends AbstractInterceptor {
        @Override
        public String intercept(ActionInvocation actionInvocation) throws Exception {
            return null;
        }
    }

    (3)方法三:

    public class InterceptorDemo2 extends MethodFilterInterceptor {
        @Override
        protected String doIntercept(ActionInvocation actionInvocation) throws Exception {
            actionInvocation.invoke();//放行
            return null;
        }
    }

    调用invoke()之前的代码叫做前处理,之后的代码叫做后处理。要是不想放行只需要返回一个字符串即可(不调用invoke()方法)。这样就不会执行后续的拦截器和Action,直接交给Result处理结果。

    8、拦截器的配置

    (1)先查看系统对拦截器的配置:

    指明拦截器类:

    <interceptors>
                <interceptor name="alias" class="com.opensymphony.xwork2.interceptor.AliasInterceptor"/>
                <interceptor name="autowiring" class="com.opensymphony.xwork2.spring.interceptor.ActionAutowiringInterceptor"/>

    默认拦截器栈(20个拦截器):

     <interceptor-stack name="defaultStack">
                    <interceptor-ref name="exception"/>
                    <interceptor-ref name="alias"/>

    指定默认拦截器栈:

    <default-interceptor-ref name="defaultStack"/>
    
            <default-class-ref class="com.opensymphony.xwork2.ActionSupport" />

    (2)按照以上步骤配置自定义拦截器(在struts.xml文件中进行配置):

    <struts>
        <package name="action" namespace="/a" extends="struts-default">
            <interceptors>
            <interceptor name="MyInter" class="pers.zhb.interceptor.InterceptorDemo2"/>
            <interceptor-stack name="MyStack">
                <interceptor-ref name="MyInter"></interceptor-ref>
                <interceptor-ref name="defaultStack"></interceptor-ref><!--引入默认的20个拦截器-->
            </interceptor-stack>
            </interceptors>
            <default-interceptor-ref name="MyStack"></default-interceptor-ref>
            <action name="Demo1" class="pers.zhb.interceptor.InterceptorDemo1" method="execute">
                <result name="success" type="dispatcher">/hello.jsp</result>
            </action>
        </package>
    </struts>

    配置拦截器共分为三个步骤:注册拦截器、注册拦截器栈、指定默认拦截器。在注册拦截器栈的时候需要将自己配置的拦截器放到系统的20个拦截器前面,这样可以保证拦截器的错误处理功能,以便在自定义拦截器出现错误的时候后面的拦截器作出处理。

    创建一个Action,调用自定义的拦截器:

    public class InterceptorDemo1 extends ActionSupport {
        public String execute(){
            System.out.println("我是调用拦截器的Action!");
            return "success";
        }
    }

    创建拦截器:

    import com.opensymphony.xwork2.ActionInvocation;
    import com.opensymphony.xwork2.interceptor.MethodFilterInterceptor;
    public class InterceptorDemo2 extends MethodFilterInterceptor {
        @Override
        protected String doIntercept(ActionInvocation actionInvocation) throws Exception {
            System.out.println("前处理");
            actionInvocation.invoke();//放行
            System.out.println("后处理");
            return null;
        }
    }

    其中invoke()方法可以调用拦截器。

    测试结果:

     

     

    9、对方法拦截的指定(即指定Action中哪些方法调用拦截器,哪些方法不调用拦截器)

    (1)指定哪些方法不调用拦截器

    struts.xml配置文件:

    <package name="action" namespace="/a" extends="struts-default">
            <interceptors>
            <interceptor name="MyInter" class="pers.zhb.interceptor.InterceptorDemo2"/>
            <interceptor-stack name="MyStack">
                <interceptor-ref name="MyInter">
                    <param name="excludeMethods">add</param>
                </interceptor-ref>
                <interceptor-ref name="defaultStack"></interceptor-ref><!--引入默认的20个拦截器-->
            </interceptor-stack>
            </interceptors>
            <default-interceptor-ref name="MyStack"></default-interceptor-ref>
            <action name="Demo1_*" class="pers.zhb.interceptor.InterceptorDemo1" method="{1}">
                <result name="success" type="dispatcher">/hello.jsp</result>
            </action>
        </package>

    这里执行Action时用到了动态方法调用,画横线的一行指定了add方法不调用拦截器。

    Action:

    public class InterceptorDemo1 extends ActionSupport {
        public String add(){
            System.out.println("ADD");
            return null;
        }
        public String delete(){
            System.out.println("DELETE");
            return null;
        }
        public String update(){
            System.out.println("UPDATE");
            return null;
        }
        public String selete(){
            System.out.println("SELETE");
            return null;
        }
        public String execute(){
            System.out.println("我是调用拦截器的Action!");
            return "success";
        }
    }

    此Action中定义了四个方法,通过配置文件来指定哪些方法调用拦截器,哪些方法不调用拦截器。

    调用拦截器的类:

    public class InterceptorDemo2 extends MethodFilterInterceptor {
        @Override
        protected String doIntercept(ActionInvocation actionInvocation) throws Exception {
            System.out.println("前处理");
            actionInvocation.invoke();//放行
            System.out.println("后处理");
            return null;
        }
    }

    运行结果:

     调用Action中的add方法时未调用拦截器。

    (2)指定哪些方法拦截:

     <param name="includeMethods">add</param>

     只需修改配置文件中的如上的配置,上面的配置为:指定add方法调用拦截器,其他方法不调用拦截器。

  • 相关阅读:
    史上最全常用正则表达式大全
    JAVA中不要用e.printStackTrace()
    JAVA中不要用e.printStackTrace()
    为什么尽量不用e.printStackTrace
    java返回集合为null还是空集合以及空集合的三种写法
    IntelliJ IDEA使用技巧——常用快捷键Mac篇
    [php] 使用laravel-modules模块化开发
    [php] 解决laravel: production.ERROR: No application encryption key has been specified
    [gitlab] 解决:remote: Ask a project Owner or Maintainer to create a default branch:
    [composer] composer 安装配置laravel 8
  • 原文地址:https://www.cnblogs.com/zhai1997/p/12210231.html
Copyright © 2020-2023  润新知