Struts2 的核心——拦截器[Interceptor]
(Interceptors) 拦截器是Struts2 的核心技术之一,或许以前对Struts2 中的某些实现感到不可思议,比如说类型转化 校验 国际化 等,那 么你的很多疑问将在这里得到解答.
什么是拦截器
拦截器,在AOP(Aspect-Oriented Programming)中用于在某个方法或字段被访问之前,进行拦截然后在之前或之后加入某些操作。拦截是AOP的一种实现策略。
在Webwork的中文文档的解释为——拦截器是动态拦截Action调用的对象。它提供了一种机制可以使开发者可以定义在一个action执行的前后执行的代码,也可以在一个action执行前阻止其执行。同时也是提供了一种可以提取action中可重用的部分的方式。
看来拦截器这东东的确很牛哦,当然拦截器本身也是一个普通的 Java 对象,而且拦截器还支持插拔的特性,不想用拦截器就不用,喜欢时再加上,不像EJB那么霸道,我想这也算是大家喜欢Struts2的一个重要原因.
提到拦截器支持插拔的特性,不得不提到Struts2中的有关拦截器的另一概念——拦截器栈[理解成拦截器链,感觉好理解点].在Struts2中允许将多个拦截器排列在一起使之成为一个集合,在访问被拦截的Action时就会按照其定义顺序被调用.
拦截器执行原理
还记得那张 big-picture吗?
注意看拦截器(interceptors)那部分,拦截器穿插在Action的执行前后,最后产生Result.
大家可以这样来看:
看来Struts2 的拦截器的实现还是相对简单的.
配置拦截器
要想让拦截器工作就必须先对拦截器进行配置,配置方式和配置其它元素差不多.为了方便,也为了满足大部分需求Struts2 提供了默认的的配置项.默认的拦截器定义在 Struts-Default package中,所以只要Action所在的package继承了Struts-Default就配置了默认的拦截器,然后就看到Struts2 很神奇的为你做很多工作了.
在配置新的拦截器之前,首先要对它定义.在配置文件中使用<interceptors.../> <interceptor.../> 标签,而且<interceptors../> 和 <interceptor>都标签要放在<package></package>标签里.例如在Struts2-core-2.2.1.jar 里struts-default.xml中拦截器是这样配置的:
<interceptors>
<interceptor name="alias"
class="com.opensymphony.xwork2.interceptor.AliasInterceptor"/>
<interceptor name="autowiring"
class="com.opensymphony.xwork2.interceptor.ActionAutowiringIntercept or"/>
<interceptors/>
这样拦截器的定义就OK了.
要想在Action中应用了所需拦截器还需要把拦截器分配到Action.你可以这样来让你的拦截器工作:
<action name="index" class="com.lele.struts2.MyAction">
<interceptor-ref name="alias">
<interceptor-ref name="autowiring">
<result>view.jsp</result>
</action>
这里在 index这个Action下就配置了先前定义的 alias 和 autowiring拦截器.理论上在一个Action下配置拦截器的数量是不受限制的.但应注意的是配置拦截器的顺序和拦截器的执行顺序.
拦截器栈
这里出现一个问题: 现在是一个Action使用了两个拦截器,假设又有一个Action要使用这两个拦截器,那这两个拦截器又要配置一遍,那假设每次都要配置5个拦截器呢?每个Action下都配置一遍吗? NO!强烈拒绝编写这种程序代码.在Struts2中提供了拦截器栈的方式来方便管理拦截器的配置.现在就来看看拦截器栈的配置:
<interceptors>
<interceptor name="alias"
class="com.opensymphony.xwork2.interceptor.AliasInterceptor"/>
<interceptor name="autowiring"
class="com.opensymphony.xwork2.interceptor.ActionAutowiringIntercept or"/>
<!-- 拦截器栈 --->
<interceptor-stack name="myStack">
<interceptor-ref name="alias"/>
<interceptor-ref name="autowiring"/>
</interceptor-stack>
<interceptors/>
这样一个拦截器栈就定义好了,当然理论上你可以定义无限多个拦截器栈,但这里也要注意拦截器栈中的拦截器的顺序.那么在使用拦截器栈还需要在定义Action时配置拦截器栈,拦截器栈和拦截器的配置相当通用,多么好的配置方式啊.ok,来看看在拦截器栈的应用配置:
<action name="index" class="com.lele.struts2.MyAction">
<interceptor-ref name="myStack">
<result>view.jsp</result>
</action>
其实在拦截器栈中不止能包含拦截器还能包含其它拦截器栈,但被包含的拦截器栈必须已经被定义.这样就提高了复用性.
默认拦截器和拦截器栈
现在在来看看我们平时写的Struts2程序,我们在配置Action时我们并没有为某个Action配置拦截器(或拦截器栈)但Struts2能帮我们做很多工作,这又是为何?
Struts2 考虑到编程的方便性在在Struts2的核心包的struts-default.xml中已经为我们定义好了默认的拦截器栈,这样使得编程工作更加简明了.那么现在我们根据自己的业务需要,我们定义了拦截器栈,我们怎样让自己定义的拦截器栈成为默认拦截器栈呢?
您只需要在<package>标签中增加:
<default-interceptor-ref name="defaultStack"/>
这样我们自己定义的defaultStack就成为了默认拦截器了,但是要知道这样就把Struts2提供给我们的默认拦截器给蔽掉了.
同样我们也可以定义默认的拦截器,方式和定义默认拦截器栈一样.
OK,就到这里了,能理解Struts2中的拦截器吗?下面章节我会说到拦截器的实现,怎样自己动手写自己的拦截器,还有Struts2中我认为比较重要的拦截器会和大家一起了解一下.
大家有什么不了解的可以和我联系,欢迎讨论
我的联系方式:
Mail: wanglehappy9112@gmail.com
PS:本篇文章已经在我的JavaEye上发表多日,今日在CSDN上同步一下,喜欢的朋友多多支持。