Struts2自定义拦截器

拦截器简介
在开发中,我们经常需要多次解决一个相同的问题,从而造成代码重复,臃肿,可读性不高等问题.也可以使用拦截器做登陆校验,由此可见,拦截器的常用之处,那么问题来了,怎么在struts2框架里面自定义拦截器呢?

1.拦截器跟过滤器的相同点,不同点

需要注意的是:过滤器只能过滤servlet,jsp 等 而拦截器只能拦截 action,它们之间是有区别的

以上是过滤器跟拦截器的不同之处,那么我们就来讲讲相同之处.

过滤器的执行流程是请求到来的时候过滤一遍,响应数据的时候再过滤一遍,拦截器也是如此,它们都需要经过俩次过滤器

这里写图片描述

2.struts2过滤器的执行流程

客户端发送请求到action,执行前端控制器,创建一个动态代理action类来执行excute方法,在excute方法里执行ActionInvocation的invoke方法,在actionInvacation方法invoke内部有一个判断,判断当前拦截器后面是否还有拦截器,如果有拦截器,就调用ActionInvacation的invoke方法,(此处形成了递归),如果当前拦截器是最后一个拦截器,那么就执行目标action,当action执行结束后,那么就会根据result执行响应操作.最后由response进行响应

流程图如下
这里写图片描述

流程时序图如下
这里写图片描述

如果还没有理解的话就自己翻翻源码,嗯多看源码有益身体健康


自定义拦截器
(拦截器 说白了,就是一个类,只是继承类(包含抽象类)或实现接口的类而已),这是我的个人理解,个人观点有可能是错误的,,,建议百度

下面介绍实现拦截器的三种方法

  • 继承抽象类 AbstractInterceptor
  • 实现Interceptor接口
  • 继承Interceptor接口的实现类MethodFilterInterceptor

我们先演示第一种代码 继承抽象类

首先我们实现抽象接口,会重写父类的方法,然后我们会发现方法提供了一个ActionInvacation的参数,看到这个参数,有没有一种似曾相识的感觉?没错,我们之前讲拦截器的时候有提到过它,它的invoke()方法,当我们已经执行完相关的操作时,我们可以调用invoke方法,让拦截器进入下一个拦截器或者是执行指定action.所以invoke()方法是关键
public class Interceptor_01 extends AbstractInterceptor{

    @Override
    public String intercept(ActionInvocation invocation) throws Exception {
        //这里进行功能操作
        System.out.println("执行了拦截器");

        if(1 == 2){  //为了方便看测试数据,我们使用false条件  
            //放行
            invocation.invoke();
            return null;
        } else {
            //如果没有达成放行要求
//          拒绝放行  不调用invoke() 就不会放行
        }

        return null;
    }

}

创建被拦截的类

public class demo1 {

    public void fun_01(){

        System.out.println("执行了demo1");
    }
}

配置struts.xml配置文件

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
    "http://struts.apache.org/dtds/struts-2.3.dtd">
    <struts>

        <package name="demo" extends="struts-default" namespace="/">
            <interceptors>   <!-- 定义一个拦截方法   name:属性自定义,不重复就行   class 是拦截器的类路径-->
                <interceptor name="fun_01" class="cn.itcast.interceptor.Interceptor_01"></interceptor>
            </interceptors>

            <!-- 被拦截的类  -->
            <action name="interceptor_*" method="{1}" class="cn.itcast.interceptor.demo1">

                <!-- 引入拦截器    name 属性需要与拦截器定义的name 一致-->
                <interceptor-ref name="fun_01"></interceptor-ref>
            </action>
        </package>
    </struts>

我们来运行一下,访问interceptor_fun_01

控制台输出结果 : “执行了拦截器”
由此可见,由于我们拦截器判断是 1 == 2 永假条件,所以消息被拦截了,

我们把拦截器判断条件改为 1 == 1 时,
控制台输出 : “执行了拦截器” “执行了demo1”


第二种拦截器定义方式 : 实现Interceptor接口

//创建一个被拦截的类
public class demo3 {

    public void fun01(){
        System.out.println("执行了demo3");
    }
}

创建一个拦截器

//实现Interceptor接口 
public class Interceptor_03 implements Interceptor {

    @Override
    public void destroy() {
        // TODO Auto-generated method stub

    }

    @Override
    public void init() {
        // TODO Auto-generated method stub

    }

    @Override
    public String intercept(ActionInvocation invocation) throws Exception {
        //执行功能操作  
        System.out.println("执行了拦截器");

        if(1 == 2 ){
            // 如果此条件成立就放行.
            invocation.invoke();
            return null;
        } 
        return null;
    }

}

编写配置文件 struts.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
    "http://struts.apache.org/dtds/struts-2.3.dtd">
    <struts>

        <package name="demo" extends="struts-default" namespace="/">
            <interceptors>   <!-- 定义一个拦截方法   name:属性自定义,不重复就行   class 是拦截器的类路径-->
                <interceptor name="fun_03" class="cn.itcast.interceptor.Interceptor_03"></interceptor>
            </interceptors>

            <action name="interceptor03_*" method="{1}" class="cn.itcast.interceptor.demo3" >

                  <!-- 引入第二种写法的拦截器  -->
                <interceptor-ref name="fun_03"></interceptor-ref>
            </action>
        </package>
    </struts>

然后我们访问interceptor03_fun01
输出结果如下 :
执行了拦截器

然后我们修改拦截器的条件为 1 == 1
输出结果如下 :
执行了拦截器 : 执行了demo3


我们来介绍第三种拦截器 (开发中常用的) 继承Intercptor的实现类MethodFilterInterceptor

//创建一个实现类
public class Interceptor_04 extends MethodFilterInterceptor{

    @Override
    protected String doIntercept(ActionInvocation invocation) throws Exception {
    system.out.print("执行了拦截器")
        if(1 == 2){  //条件不成立
//          条件成立,就放行
            invocation.invoke();
            return null;
        }
        return null;
    }

}

创建一个被拦截类

public class demo4 {
    //为了体现该方法的特别,暴露出俩个方法
    public void fun01(){
        System.out.println("执行了被拦截类 的fun01方法");
    }

    public void fun02(){
        System.out.println("执行了被拦截类 的fun02方法");
    }
}

编写xml配置文件

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
    "http://struts.apache.org/dtds/struts-2.3.dtd">
    <struts>

        <package name="demo" extends="struts-default" namespace="/">
            <interceptors>   <!-- 定义一个拦截方法   name:属性自定义,不重复就行   class 是拦截器的类路径-->
                <interceptor name="fun_04" class="cn.itcast.interceptor.Interceptor_04"></interceptor>
            </interceptors>

            <action name="interceptor04_*" method="{1}" class="cn.itcast.interceptor.demo4" >

                  <!-- 引入第二种写法的拦截器  -->
                <interceptor-ref name="fun_04"></interceptor-ref>
            </action>
        </package>
    </struts>

进行代码测试
分别测试 fun01 fun02俩个方法
输出结果分别是 :

  • 执行了拦截器
  • 执行了拦截器

然后我们在拦截器配置里增加

<interceptors>   <!-- 定义一个拦截方法   name:属性自定义,不重复就行   class 是拦截器的类路径-->
                <action name="interceptor04_*" method="{1}" class="cn.itcast.interceptor.demo4" >
                  <!-- 引入第二种写法的拦截器  -->
                <interceptor-ref name="fun_04">
                    <param name="excludeMethods">fun01</param>  <!-- fun01是方法名称,意思是不拦截次方法 -->
                </interceptor-ref>
            </action>

然后我们再运行代码进行测试
分别访问 fun01 和 fun02方法
输出结果如下

  • 执行了被拦截类 的fun01方法 执行fun01没有经过拦截器
  • 执行了被拦截类 的fun01方法 执行了拦截器 执行fun02经过了拦截器,由次可知,
<param name="excludeMethods">fun01</param> 该代码的作用是声明方法,该声明的方法不会被拦截器拦截 

param name的另外一个属性includeMethods  
作用是拦截被该param声明的方法,由于时间问题,就不测试了 

本人也是菜鸟一枚,如果有什么地方讲的不好,或者不对,欢迎指出.鞋靴

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值