拦截器体系是Struts 2框架的重要组成部分,可以把Struts 2理解成一个空容器,而大量的内建拦截器完成了该框架的大部分操作。Struts 2的拦截器有如下两个特点:
- Struts 2拦截器是可插拔式的设计,不管是否应用某个拦截器,对于Struts 2框架不会有任何影响;
- Struts 2拦截器由struts-default.xml、struts.xml等配置文件进行管理,具有很大的可扩展性,开发者很容易扩展自己的拦截器。
在Sturts 2中的工作机制如下图所示。
在用户发出请求后,StrutsPrepareAndExecuteFilter会将其拦截,之后,大量的拦截器将会对该请求进行处理,最后才会调用相应的Action实例处理请求。
一、拦截器的配置与使用
1. 配置拦截器
拦截器的配置主要是在struts.xml文件中进行的。
首先需要对拦截器进行定义,即为拦截器指定一个拦截器名。其最简单的格式如下:
<interceptor name="拦截器名" class="拦截器实现类" />
不过,在有些时候还需要在配置拦截器时传入参数,那么就需要在<interceptor .../>元素中使用<param .../>元素进行参数传入。其格式如下:
<interceptor name="拦截器名" class="拦截器实现类">
<!--prama元素可以出现0~无限多次-->
<param name="参数名">参数值</param>
</interceptor>
除此之外,还可以将多个拦截器连在一起组成拦截器栈。拦截器栈使用<interceptor-stack .../>元素定义,同时在其中使用<interceptor-ref .../>来引用拦截器。其格式如下:
<interceptor-stack name="拦截器栈名">
<interceptor-ref name="拦截器名" />
<interceptor-ref name="拦截器名" />
<interceptor-ref name="拦截器名" />
......
</interceptor-stack>
从程序功能角度来讲,拦截器栈和拦截器的功能是统一的,可以将其看作是一个更大的拦截器。所以,在拦截器栈中,同样可以包含拦截器栈。
为拦截器指定参数有两个时机:
- 定义拦截器时指定:这种参数值将作为默认参数值;
- 使用拦截器时指定:在配置Action时为拦截器参数指定值,这种方式会覆盖默认值。
2.使用拦截器
<interceptors>
<interceptor name="first" class="..." />
<interceptor name="second" class="..." >
<param name="...">value</param>
</interceptor>
......
</interceptors>
......
<action name="..." class="...">
<result>...</result>
......
<interceptor-ref name="defaultStack" />
<interceptor-ref name="first" />
<interceptor-ref name="second" >
<param name="...">value</param>
</interceptor-ref>
</action>
其中,defaultStack是系统默认的拦截器栈。
二、自定义拦截器的实现
除了可以使用Struts 2的内建拦截器外,也可以使用自定义的拦截器来实现一些系统逻辑相关的通用功能。
开发自己的拦截器类,应该实现com.opensymphony.xwork2.interceptor.Interceptor接口。该接口需要实现三个方法:
- init():在该拦截器被实例化之后,在该拦截器执行拦截之前,系统回调该方法。每个拦截器其init()方法只执行一次。
- destroy():该方法与init()方法对应,在拦截器实例被小会之前,系统回调该方法。
- intercept(ActionInvocation invocation):该方法是用户需要实现的拦截动作。其中,参数invocation包含了被拦截的Action的引用,可以调用该参数的invoke方法,将控制权转给下一个拦截器或者Action的execute方法。
除此之外,Struts 2还提供了AbstractInterceptor类,该类提供了init()和destroy()方法的空实现,继承这个类实现自定义拦截器会更简单。
拦截方法的拦截器
在默认情况下,如果为某个Action定义了拦截器,则这个拦截器会拦截该Action内的所有方法。但是在某些情况下,只需要拦截指定方法,此时就需要使用Struts 2拦截器的方法过滤特性。
实现方法过滤特性,需要继承MethodFilterInterceptor类。该类的intercept已经实现了对Action的拦截行为,但真正的拦截逻辑还需要开发者提供,也就是通过回调doIntercept方法实现。在MethodFilterInterceptor中,额外增加了两个方法:
- public void setExcludeMethods(String excludeMethods):排除需要过滤的方法;
- public void setIncludeMethods(String includeMethods):设置需要过滤的方法。
在使用该拦截器时,可以通过name属性为excludeMethods和includeMethods的<param .../>元素来指定不需要拦截和需要拦截的方法。