拦截器的概念
- 拦截器(Interceptor)是Struts2的核心组成部分。很多功能都是构建在拦截器基础之上的,例如文件的上传和下载、国际化、转换器和数据校验等,Struts2利用内建的拦截器,完成了框架内的大部分操作。
- 在Struts2文档中对拦截器的解释为--拦截器是动态拦截Action调用的对象。它提供了一种机制,使开发者可以定义一个特定的功能模块,这个模块可以在Action执行之前或者之后运行,也可以在一个Action执行之前阻止Action执行。同时也提供了一种可以提取Action中可重用的部分的方式。
- 拦截器是Struts2 更高层次的解耦,无须侵入框架本身便可以添加新的功能。
- 拦截器是AOP( Aspect-Oriented Programming)的一种实现,底层通过动态代理模式完成。
拦截器实现原理
- 拦截器围绕着Action和Result的执行而执行,其工作方式如上图。
- 从图中可以看到,在Action和Result执行之前,为Action配置的拦截器将首先被执行,在Action和Result执行之后,拦截器将重新获得控制权,然后按照与先前调用相反的顺序依次执行。在整个执行过程中,任何一个拦截器都可以选择直接返回,从而终止余下的拦截器、Action和Result的执行。例如:当一个未授权的用户访问受保护的资源时,执行身份验证的拦截器可以直接返回。
拦截器和过滤器的区别
区别:


如果在其他的拦截器配置中出现了同名的参数,则前面配置的参数将被覆盖掉。
在struts.xml中可以配置多个拦截器,它们被包在<interceptors></interceptors>之间,例如下面的配置:

注意:一旦继承了struts-default包(package),所有Action都会默认调用拦截器栈 ---defaultStack。但是当在Action配置中加入“<interceptor-ref name=”..“ />”则会覆盖defaultStack,所以在action中写拦截器引用时,需要显示引用defaultStack(而且最好在第一句)。
- 拦截器是基于java的反射机制的,而过滤器是基于函数回调。
- 拦截器不依赖与servlet容器,而过滤器依赖与servlet容器。
- 拦截器只能对action请求起作用,而过滤器则可以对几乎所有的请求起作用。
- 拦截器可以访问action上下文、值栈里的对象,而过滤器不能。
- 在action的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一次
struts2内置拦截器
Struts2内建了大量的拦截器,这些拦截器以name-class对的形式配置在struts-default.xml文件中,其中name是拦截器的名字,就是以后使用该拦截器的唯一标识;class则指定了该拦截器的实现类,如果我们定义的package继承了Struts2的struts-default包,则可以自由使用下面定义的拦截器,否则必须自己定义这些拦截器。
拦截器的配置
拦截器的配置是在struts.xml中完成的,定义一个拦截器使用<interceptor…/>标签,其格式如下:
<interceptor name="拦截器名" class="拦截器实现类"></interceptor>
<interceptor name="拦截器名" class="拦截器实现类"></interceptor>
这种情况的应用非常广。有的时候,如果需要在配置拦截器时就为其传入拦截器参数,只要在<interceptor..>与</interceptor>之间配置<param…/>标签即可传入相应的参数。其格式如下:
<interceptor name="拦截器名" class="拦截器实现类 ">
<param name="参数名">参数值</param>
...//如果需要传入多个参数,可以一并设置
</interceptor>
如果在其他的拦截器配置中出现了同名的参数,则前面配置的参数将被覆盖掉。
在struts.xml中可以配置多个拦截器,它们被包在<interceptors></interceptors>之间,例如下面的配置:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<package name="default" extends="struts-default">
<interceptors>
<interceptor name="拦截器名1" class="拦截器类1"></interceptor>
<interceptor name="拦截器名2" class="拦截器类2"></interceptor>
...
<interceptor name="拦截器名n" class="拦截器类n"></interceptor>
</interceptors>
...//action配置
</package>
</struts>
拦截器是配置在包下的。在包下配置了一系列的拦截器,但仅仅是配置在该包下,并没有得到应用。如果要应用这些拦截器,就需要在<action>配置中引用这些拦截器,
格式为:
<interceptor-ref name="…">
例:
<action name="Action名" class="Action类">
<interceptor-ref name="defaultStack"></interceptor-ref>
<interceptor-ref name="拦截器1"></interceptor-ref>
<interceptor-ref name="拦截器2"></interceptor-ref>
</action>
拦截器栈
在很多时候,有些指定的拦截器需要被多个Action所使用,这个时候,如果我们为每一个Action都分别配置拦截器的话,不仅麻烦,而且不利后期的维护,此时就需要用到拦截器栈。
所谓拦截器栈就是将一些拦截器组合起来进行统一管理。格式为:
<interceptor-stack name=“…"></interceptor-stack>
<interceptor-stack name=“…"></interceptor-stack>
其实,在Struts 2框架中也配置有很多拦截器栈,在Struts 2的struts-default.xml中可以发现有如下拦截器栈的配置:
拦截器栈配置完成后就可以在<action>中对其引用了,一个action引用拦截器栈的格式如下:
<interceptors>
<interceptor-stack name="myStack">
<interceptor-ref name="defaultStack"></interceptor-ref>
<interceptor-ref name="拦截器1"></interceptor-ref>
<interceptor-ref name="拦截器2"></interceptor-ref>
</interceptor-stack>
</interceptors>
<action name="Action名" class="Action类">
<interceptor-ref name="myStack"></interceptor-ref>
</action>
注意:一旦继承了struts-default包(package),所有Action都会默认调用拦截器栈 ---defaultStack。但是当在Action配置中加入“<interceptor-ref name=”..“ />”则会覆盖defaultStack,所以在action中写拦截器引用时,需要显示引用defaultStack(而且最好在第一句)。
默认拦截器
- <default-interceptor-ref name=“…”>
- 如果为Action指定了拦截器,则默认拦截器不再起作用,必须显式指定默认截拦器