1)预定义拦截器
Struts2有默认的拦截器配置,也就是说,虽然我们没有主动去配置任何关于拦截器的东西,但是Struts2会使用默认引用的拦截器。由于Struts2的默认拦截器声明和引用都在这个Struts-default.xml里面,因此我们需要到这个文件的struts-default包里去看一下。定义如下:
View Code
params拦截器
这个拦截器是必不可少的,因为就是由它偷偷的把请求参数设置到相应的Action的属性去的,并自动进行类型转换。
staticParams拦截器
将struts.xml配置文件里定义的Action参数,设置到对应的Action实例中,Action参数使用<param>标签,是<action>标签的子元素。struts.xml的示例如下:
这要求Action中一定要有一个account的属性,并有相应的getter/setter方法。运行的时候,Action的account属性在初始化过后,会接到这里的赋值“test”。
注意:params拦截器和staticParams拦截器都会为Action的属性赋值,如果碰到了都要赋同一个值呢,比如request里面有account参数,而struts.xml中也有account参数,最终的值是谁?其实是Action初始化过后,就会把struts.xml中配置的数据设置到Action实例中相应的属性上去。然后,把用户请求的数据设置到Action实例中相应的属性上去。很明显最后的值是用户请求中account的数据。
timer拦截器
该拦截器可以记录ActionInvocation余下部分执行的时间,并做为日志信息记录下来,便于寻找性能瓶颈。也就是说,该拦截器可以记录Action运行的时间。
logger拦截器
在日志信息中输出要执行的Action信息
,这样,在调试的时候,就能很快的定位到这个对应的Action了。
2)拦截器配置说明
<interceptor>元素用来定义一个拦截器,这里仅仅是一个定义,还没有任何一个Action来引用它。里面的name属性作为唯一标志,而class属性就是这个拦截器的实现类。拦截器的实现类都应该是com.opensymphony.xwork2.interceptor.Interceptor这个接口的实现类。
<interceptor-stack>定义了一个拦截器栈,这个栈中可以引用其他已经定义好的拦截器。拦截器栈简化了动作类Action在引用拦截器时的操作。
因为大多数动作类Action在引用拦截器的时候都不会仅仅引用一个拦截器,而是引用一组拦截器,而多个动作类Action大概又会引用同一组拦截器,这时候,为了引用的方便,可以把多个拦截器组合成一个拦截器栈。Action在引用的时候,只需要引用这个拦截器栈就可以了,而不是引用每一个拦截器。下面看一下struts-2.1.dtd对于<action>元素的定义:
action元素后面出现的interceptor-ref子元素后面用*来修饰,这说明一个action元素可以有不限个数的interceptor-ref子元素。那么在<action>元素中,如何使用<interceptor-ref>子元素呢?其实很简单,只需要在<action>元素中,配置需要的<interceptor-ref>子元素就可以了,<interceptor-ref>子元素里面配置需要使用的拦截器的名称,比如:
<interceptor-ref>子元素中的name,不仅仅可以是一个已经定义好的拦截器的名称,还可以是一个已经定义好的拦截器栈的名称。上面的示例,就引用了一个拦截器和一个拦截器栈。
<default-interceptor-ref>在包上声明包内所有的Action都使用的拦截器
先看一下struts-2.1.dtd对于<package>元素的定义:
其实,在配置自己的package的时候所扩展的struts-default包里面,就已经定义了一个<default-interceptor-ref>,在Struts-default.xml中定义的struts-default包内,有如下定义:
正是因为有这个定义,我们都没有主动去配置拦截器,但实际上,是有拦截器在运行并执行很重要的工作,只不过是使用的默认的拦截器,我们不知道罢了。
3)拦截器的调用顺序
在学习了预定义拦截器的配置使用之后,接下来看看<action>元素引用拦截器的调用顺序。在拿到一个动作类的声明<action>元素后,如何找到它引用的拦截器呢?
1:首先,要找它自己有没有声明拦截器的引用,即<action>元素有没有<interceptor-ref>子元素,如果有,则不用继续再找,直接使用这些拦截器,如果没有,下一步。
2:其次,找这个<action>所在的包有没有声明默认的拦截器引用,即<package>元素的<default-interceptor-ref>子元素,
如果有,则不用继续再找,直接使用这些拦截器,如果没有,下一步。
3:最后,递归地寻找这个包的父包有没有声明默认的拦截器引用,直到找到有拦截器引用就为止。
特别注意:这三个地方的定义是覆盖的关系,什么意思呢?就是如果<action>里面声明了拦截器引用,那么就以它的为准,其他的定义就无效了。也即是<action>里面的拦截器引用声明会覆盖<package>里面的缺省拦截器声明,而<package>里面的缺省拦截器声明又会覆盖父包的<package>里面的缺省拦截器声明,以此类推。
4)全局拦截器的配置
参考资料: