框架提供默认的拦截器栈可以满足大部分应用程序的需要的,所以大部分应用并不需要修改默认的拦截器栈来新增加新的拦截器。
许多动作(Action)有着共同的问题需要处理。另外,不同的动作,面临的需要处理的问题也不全部相同。例如,一些动作需要表单验证,一些动作可能需要文件上传的预处理,一些动作需要避免重复提交表单,还有一些动作在网页展现之前需要下拉列表和其它的控制的预操作。
通过使用拦截器策略,Struts2框架很方便的共享这些问题的解决方法。当你请求和动作映射的资源的时候,框架就会调用动作对象。但是在要调用的动作执行之前,调用可能会被另外的对象拦截。在动作执行完毕后,调用还可能再一次被拦截。我们称拦截动作的调用的对象为拦截器。
下面,我们来看看拦截器的真面目
一、理解拦截器
拦截器可以在动作调用前或者后来执行代码。框架大部分核心方法被实现为拦截器。例如,类型转换,对象数量,验证,文件上传,网页预准备等等,都是通过拦截器实现的。每一个拦截器都可以随意插入,所以你可以 准确的决定哪一类型的动作需要拦截器提供支持。
由于拦截器和动作紧密相关,所以先来看看动作(Action)的生命周期,如图
首先Servlet分发器负责实例化一个新的动作代理,接着调用动作代理的exeute方法。动作代理取得动作的名称,方法,命名空间等等东西,在调用动作方法前,请求会经过拦截器拦截,动作返回结果后又可能被其它的拦截器拦截发到下一个动作的请求。只要动作的执行完成了,请求就会被传送到结果处理类作为结果。
在一些情况下,拦截器还可以阻止一个动作的执行,比如在重复提交表单或者验证失败的情况下。拦截器可以在动作执行前改变动作动作的状态。
拦截器定义在拦截器栈里面,指定了执行的顺序。拦截器在栈里面的执行顺序是十分重要的,按配置顺序依次执行。
看看拦截器的配置两个例子
1、在<package></package>
标签下面配置,在<action></action>
标签下面分别使用
<package name="default" extends="struts-default">
<interceptors>
<interceptor name="timer" class=".."/>
<interceptor name="logger" class=".."/>
</interceptors>
<action name="login"
class="tutorial.Login">
<interceptor-ref name="timer"/>
<interceptor-ref name="logger"/>
<result name="input">login.jsp</result>
<result name="success"
type="redirectAction">/secure/home</result>
</action>
</package>
2、在<package></package>
标签下面配置并且添加拦截器栈,在<action></action>
标签下面使用拦截器栈
<package name="default" extends="struts-default">
<interceptors>
<interceptor name="timer" class=".."/>
<interceptor name="logger" class=".."/>
<interceptor-stack name="myStack">
<interceptor-ref name="timer"/>
<interceptor-ref name="logger"/>
</interceptor-stack>
</interceptors>
<action name="login"
class="tutuorial.Login">
<interceptor-ref name="myStack"/>
<result name="input">login.jsp</result>
<result name="success"
type="redirectAction">/secure/home</result>
</action>
</package>
在实际开发使用拦截器的配置的时候,我们可以在struts2提供的struts-default.xml
文件里面查看。每一个拦截器的配置都对应一个拦截器类。
在实现自定义拦截器类的时候,继承自AbstractInterceptor
或者其的子类就可以。MethodFilterInterceptor
是一个比较好用的拦截器类,继承自它,可以指定方法被拦截器拦截或者不拦截。具体用法这里暂不介绍。
二、覆写拦截器的参数
覆写拦截器参数有两个方法。
- 覆写拦截器栈里面的参数
格式是
<param name="workflow.excludeMethods">myWorkflowExcludeMethod</param>
原有方法+”.”+excludeMethod 标签体是自定义替代的方法。
<action name="myAction" class="myActionClass">
<interceptor-ref name="defaultStack">
<param name="validation.excludeMethods">myValidationExcludeMethod</param>
<param name="workflow.excludeMethods">myWorkflowExcludeMethod</param>
</interceptor-ref>
</action>
- 覆写指定拦截器的参数
<action name="myAction" class="myActionClass">
<interceptor-ref name="exception"/>
<interceptor-ref name="alias"/>
<interceptor-ref name="params"/>
<interceptor-ref name="servletConfig"/>
<interceptor-ref name="prepare"/>
<interceptor-ref name="i18n"/>
<interceptor-ref name="chain"/>
<interceptor-ref name="modelDriven"/>
<interceptor-ref name="fileUpload"/>
<interceptor-ref name="staticParams"/>
<interceptor-ref name="params"/>
<interceptor-ref name="conversionError"/>
<interceptor-ref name="validation">
<param name="excludeMethods">myValidationExcudeMethod</param>
</interceptor-ref>
<interceptor-ref name="workflow">
<param name="excludeMethods">myWorkflowExcludeMethod</param>
</interceptor-ref>
</action>
三 、拦截器的执行顺序
拦截器配置
<interceptor-stack name="xaStack">
<interceptor-ref name="thisWillRunFirstInterceptor"/>
<interceptor-ref name="thisWillRunNextInterceptor"/>
<interceptor-ref name="followedByThisInterceptor"/>
<interceptor-ref name="thisWillRunLastInterceptor"/>
</interceptor-stack>
执行顺序
thisWillRunFirstInterceptor
thisWillRunNextInterceptor
followedByThisInterceptor
thisWillRunLastInterceptor
(
……
……
……
)
thisWillRunLastInterceptor
followedByThisInterceptor
thisWillRunNextInterceptor
thisWillRunFirstInterceptor