第一节:Struts2的拦截器
1.1 拦截器的概述:
拦截器,在AOP(Aspect - Oriented Programming)中用于在某个方法或字段被访问之前,进行拦截然后在之前或之后加入某些操作。拦截是AOP的一种实现策略。
在WebWork的中文文档的解释为——拦截器是动态拦截Action调用的对象。它提供了一些机制可以使开发者可以定义在一个action执行的前后执行的代码,也可以在一个Action执行前阻止其执行。同时也是提供了一种可以提取action中可重用的部分的方式。
谈到拦截器,还有一个词——拦截器链(Interceptor Chain,在Struts2中称为拦截栈Interceptor Stack)。拦截器链就是将拦截器按一定的顺序联结成一条链。在访问被拦截的方法或字段时,拦截器链中的拦截器就会按其之前定义的顺序被调用。
1.2 拦截器的实现原理:
拦截器方法都是通过代理的方式来调用的。当请求送达Struts2的ServletDispatcher时,Struts2会查找配置文件,并根据其配置实例化相对的拦截器对象,然后串成一个列表,最后一个一个地调用列表中的拦截器。
Struts2拦截器是可插拔的,拦截器是AOP的一种实现。Struts2拦截器栈就是将拦截器按一定的顺序联结成一条链。在访问被拦截的方法或字段时,Struts2拦截器链中的拦截器就会按其之前定义的顺序被调用。
1.3 拦截器的执行流程
1.4 自定义拦截器
若需要实现拦截器类,就需要直接或间接的实现com.opensymphony.xwork2.interceptor接口,其接口定义代码如下:
import com.opensymphony.xwork2.ActionInvocation;
import java.io.Serializable;
public interface Interceptor extends Serializable {
void destroy();
void init();
String intercept(ActionInvocation var1) throws Exception;
}
该接口提供了三个方法,其具体介绍如下:
- void init():该方法在拦截器被创建后会立即被调用,它在拦截器的生命周期内只被调用一次,可以在该方法中对相关资源进行必要的初始。
- void destroy():该方法与init方法相对应,在拦截器被销毁之前,将调用该方法来释放和拦截器相关的资源。它在拦截器的生命周期内,也只被调用一次。
- String intercept(ActionInvocation invocation)throws Exception:该方法是拦截器的核心方法,用来添加真正执行拦截工作的代码,实现具体的拦截操作。它返回一个字符串作为逻辑视图,系统根据返回的字符串跳转到对应的视图资源。每拦截一个动作请求,该方法都会被调用一次。该方法的ActionInvocation参数包含了被拦截Action的引用,可以通过该参数的invoke()方法,将控制权给下一个拦截器或者转给Action的execute()方法。
如果需要自定义拦截器,只需要实现Interceptor接口的三个方法即可。然而在实际的开发中,除了实现Interceptor接口可以自定义拦截器外,更常用的一种方式是继承抽象拦截器类AbstracIntercepter。该类实现了Interceptor接口,并且提供了init()方法和destory()方法的空实现。使用时,可以继承该抽象类,而不用实现那些不必要的方法。拦截器类AbstractInterceptor中定义的方法如下所示:
public abstract class AbstractInterceptor implements Interceptor {
public AbstractInterceptor() {
}
public void init() {
}
public void destroy() {
}
public abstract String intercept(ActionInvocation var1) throws Exception;
}
从上述代码中可以看出,AbstractInterceptor类已经实现了Interceptor接口的所有方法,一般情况下,只需继承AbstractInterceptor类,实现interceptor()方法就可以创建自定义拦截器。
只有当自定义的拦截器需要打开系统资源时,才需要覆盖AbstracInterceptor类的init()方法和destroy()方法。与实现Interceptor接口相比,继承AbstractInterceptor类的方法更为简单。
1.5 拦截器的配置
- 拦截器
要想让拦截器起作用,首先要对它进行配置。拦截器的配置是在struts.xml文件中完成的,它通常以<interceptor>标签开头,以</interceptor>标签结束。定义拦截器的语法格式如下:
<interceptors>
<interceptor name="interceptorDemo01" class="com.seapp.struts2.interceptor.MyInterceptor02">
<param name="paramName">paramValue</param>
</interceptor>
</interceptors>
上述语法格式中,name属性用来指定拦截器的名称,class属性用于指定拦截器的实现类。有时,在定义拦截器时需要传入参数,这时需要使用<param>标签,其中name属性用来指定参数的名称,paramValue表示参数的值。
- 在实际开发中,经常需要在Action执行前同时执行多个拦截动作,如:用户登录检查、登录日志记录以及权限检查等。这时,可以把多个拦截器组成一个拦截器栈。在使用时,可以将栈内多个拦截器当成一个整体来引用。当拦截器栈被附加到一个Action上时,在执行Action之前必须先执行拦截器栈中的每一个拦截器。
-拦截器:
<interceptors>
<interceptor-stack name="interceptorStackName">
<interceptor-ref name="interceptorName"/>
...
</interceptor-stack>
</interceptors>
在上述的语法中,interceptorStackName值表示配置的拦截器的名称;interceptorName值表示拦截器的名称。除此之外,在一个拦截器栈中还可以包含另一个拦截器栈,示例代码如下:
<interceptors>
<!--声明拦截器-->
<interceptor name="interceptor" class="com.seapp.struts2.interceptor.MyInterceptor">
</interceptor>
<interceptor name="interceptorDemo01" class="com.seapp.struts2.interceptor.MyInterceptor02">
<param name="paramName">paramValue</param>
</interceptor>
<!--定义一个拦截器栈myStack,该拦截器栈中包含两个拦截器和一个拦截器栈-->
<interceptor-stack name="myStack">
<interceptor-ref name="defaultStack"/>
<interceptor-ref name="interceptor"/>
<interceptor-ref name="interceptorDemo01"/>
</interceptor-stack>
</interceptors>
在上述代码中,定义的拦截器栈是myStack,在myStack栈中,除了引用了两个自定义的拦截器interceptor和interceptorDemo01外,还引用了一个内置拦截器栈defaultStack,这个拦截器是必须要引入的。
网友评论