欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Struts2中的拦截器概述

程序员文章站 2022-07-09 17:16:01
...

在开始讲解之前,先分享一篇不错的关于Struts2拦截器的讲解博客:Struts2拦截器详解

一、拦截器的概述

拦截器,在AOP(Aspect-Oriented Programming)中用于在某个方法或字段被访问前,进行拦截,然后在之前或在之后加入某些操作。拦截是AOP的一种实现策略。现实开发中有很多的应用场景,比如:用户登录检查、登录日志记录以及权限检查等等。

Struts2的执行流程如下图:

Struts2中的拦截器概述

拦截器是一种可以在让用户在Action执行之前和Result执行之后进行一些功能处理的机制。 而且拦截器在action执行之前和result执行之后的顺序是相反的,即:Interceptor1—Interceptor2—Interceptor3—Action—Result–Interceptor3—-Interceptor2—-Interceptor1。

struts2里面封装的功能都是在拦截器里面。有很多拦截器,但不是每次这些拦截器都执行,每次执行默认的拦截器。

Struts2里面默认的拦截器位置:struts2-core-2.xxxx.jar—->struts-default.xml,在这里面配置了很多的拦截器,但是只执行默认配置的那些拦截器。

拦截器链,又叫拦截器栈,就是将拦截器按照一定的顺序联

二、拦截器的原理

大部分时候,拦截器方法都是通过代理的方式来调用的。当请求到达Struts2的ServletDiapatcher时,Struts2会查找配置文件,并根据其配置实例化相应的拦截器对象,然后串成一个列表,最后一个一个地调用列表中的拦截器。另外,Struts2中的拦截器都是可插拔的。

三、自定义拦截器

方法一:实现Interceptor接口

com.opensymphony.xwork2.interceptor.Interceptor接口的代码如下:

public interface Interceptor extends Serializable{
    void init();
    void destroy();
    String intercept(ActionInvocation invocation)throws Exception; 
}

可以看出来,该接口提供了三个方法,具体介绍如下:

(1):void init():该方法在拦截器被创建后立即被调用,它在拦截器的生命周期内只被调用一次,可以在该方法中对相关的资源进行必要的初始化;

(2):void destroy():该方法与init()方法相对应,在拦截器实例被销毁之前,将调用该方法来释放和拦截器有关的资源。它在拦截器的生命周期内,也只被调用了一次。

(3):String intercept(ActionInvocation invocation)throws Exception: 该方法是拦截器的核心方法,用来添加真正执行拦截工作的代码,实现具体的拦截操作。它返回一个字符串作为逻辑视图,系统根据返回的字符串跳转到对应的视图资源。每拦截一个动作请求,该方法就会被调用一次。该方法的ActionInvocation参数包含了被拦截的Action的引用,可以通过该参数的invoke()方法,将控制权转给下一个拦截器或者转给Action的execute()方法。

方法二:继承AbstractInterceptor类(常用,更简单一点)

除了实现Interceptor接口外,实际开发中更常用的是继承抽象拦截器类:AbstractInterceptor。该类实现了Interceptor接口,并且提供了init()和destroy()方法的空实现。使用时可以直接继承该抽象类,而不用实现那些不必要的方法。

public abstract class AbstractInterceptor implements Interceptor{
    public void init(){}
    public void destroy(){}
    public abstract String intercept(ActionInvocation invocation) throws Exception; 
}

四、拦截器的配置

拦截器的配置是在struts.xml文件中完成的,它通过<interceptor>标签开头。

1、拦截器的配置

<interceptor name="interceptorName" class="interceptorClass">
    <param name="paramName">paramValue</param>
</interceptor>

name属性用来指定拦截器的名称,class属性用来指定拦截器的实现类。有时定义拦截器需要传入参数,这时需要使用<param>标签,其中name属性用来指定参数的名称,paramValue表示参数的值。

2、拦截器栈的配置

在实际开发中,经常需要在Action执行前同时执行多个拦截器动作,如:用户登录检查、登录日志记录以及权限检查等,这时,可以把多个拦截器组成一个拦截器栈。在使用时,可以将栈内的多个拦截器当成一个整体来引用。当拦截器栈被附加到一个Action上时,在执行Action之前必须先执行拦截器栈中的每一个拦截器。

定义拦截器栈使用<interceptors>元素和<interceptor-stack>子元素,当配置多个拦截器时,需要使用<interceptor-ref>元素来指定多个拦截器,配置语法如下:

<interceptors>
    <interceptor-stack name="interceptorStackName">
        <interceptor-ref name="interceptorName1"/>
        <interceptor-ref name="interceptorName1"/>
        ...
    </interceptor-stack>
</interceptors>

在上述语法中,interceptorStackName值表示配置的拦截器栈的名称,interceptorName表示拦截器的名称。另外,在一个拦截器栈中还可以包含其他拦截器栈,配置语法如下:

<package name="default" extends="struts-default" namespace="/">
    <!-- 声明拦截器 -->
    <interceptors>
        <interceptor name="interceptor1" class="interceptorClass">
        <interceptor name="interceptor2" class="interceptorClass">
        <!-- 定义一个拦截器栈myStack,该拦截器栈中包含两个拦截器和一个拦截器栈 -->
        <interceptor-stack name="myStack">
            <!-- defaultStack这个内置的拦截器栈是必须要引入的 -->
            <interceptor-ref name="defaultStack"/>
            <interceptor-ref name="interceptor1"/>
            <interceptor-ref name="interceptor2"/>
        </interceptor-stack>
    </interceptors>
</package>

 

相关标签: Struts2 拦截器