虽然Struts2框架提供了许多的拦截器,并且这些内建的拦截器实现了Struts2的大部分功能,因此,大部分的Web应用的通用功能,都可以通过直接使用这些拦截器来完成,但是还是有一些系统逻辑相关的通用功能,可以通过自定义拦截器来实现。值得一提的是,Struts2的拦截器机制非常的简单好用。
我们想要开发自己的拦截器类,通常有两种方式,一个是实现Interceptor接口,另一个是继承AbstractInterceptot类,相比较而言,通过继承AbstractInterceptor类来实现自定义拦截器更加的简单。
方式1:实现Interceptor接口
先来看看该接口的定义,代码如下:
public interface Interceptor extends Serializable {
/**
* Called to let an interceptor clean up any resources it has allocated.
*/
void destroy();
/**
* Called after an interceptor is created, but before any requests are processed using
* {@link #intercept(com.opensymphony.xwork2.ActionInvocation) intercept} , giving
* the Interceptor a chance to initialize any needed resources.
*/
void init();
/**
* Allows the Interceptor to do some processing on the request before and/or after the rest of the processing of the
* request by the {@link ActionInvocation} or to short-circuit the processing and just return a String return code.
*
* @param invocation the action invocation
* @return the return code, either returned from {@link ActionInvocation#invoke()}, or from the interceptor itself.
* @throws Exception any system-level error, as defined in {@link com.opensymphony.xwork2.Action#execute()}.
*/
String intercept(ActionInvocation invocation) throws Exception;
}
通过上面的接口可以看出,该接口里包含了三个方法。
init():在拦截器被实例化之后,在该拦截器执行拦截之前,系统将回调该方法。对于每个拦截器而言,其init()方法只执行一次。因此该方法的方法体主要用于初始化各种资源,比如数据库连接等。
destroy():该方法与init()方法对应。在拦截器实例被销毁之前,系统将回调该拦截器的destroy方法,该方法用于销毁在init方法里打开的资源。
intercept(ActionInvocation invocation):该方法是用户需要实现的拦截动作。就像Action的execute()方法一样,intercept方法会返回一个字符串作为逻辑视图。如果该方法直接返回了一个字符串,系统将会跳转到该逻辑视图对应的实际视图资源,不会调用被拦截的Action。该方法的ActionInvocation参数包含了被拦截的Action的引用,可以通过调用该参数的invoke方法,将控制权转交给下一个拦截器,或者转给Action的execute方法。
方式2:继承AbstractInterceptor抽象类
我们可以打开源码查看一下这个类的代码是如何定义的。
public abstract class AbstractInterceptor implements Interceptor {
/**
* Does nothing
*/
public void init() {
}
/**
* Does nothing
*/
public void destroy() {
}
/**
* Override to handle interception
*/
public abstract String intercept(ActionInvocation invocation) throws Exception;
}
从源码中我们可以看到,其实AbstractInerceptor实现了Interceptor接口,同样具有三个方法,当然这三个方法是实现自Interceptor接口,只不过init和destroy方法都是空实现,如果我们实现的拦截器不需要打开资源,则可以无须实现这两个方法,从这个角度讲,继承AbstractInterceptor类来实现自定义拦截器会更加的简单方便。
下面我简单写一个拦截器,来说明如何实现自定义拦截器,鉴于上面的两种方式其本质是一样的,都是实现了Interceptor接口,因此我就第二种方式为例,给出代码示例,如下:
public class SimpleInterceptor
extends AbstractInterceptor
{
// 简单拦截器的名字
private String name;
// 为该简单拦截器设置名字的setter方法
public void setName(String name)
{
this.name = name;
}
public String intercept(ActionInvocation invocation)
throws Exception
{
// 取得被拦截的Action实例
LoginAction action = (LoginAction)invocation.getAction();
// 打印执行开始的时间
System.out.println(name + " 拦截器的动作---------" +
"开始执行登录Action的时间为:" + new Date());
// 取得开始执行Action的时间
long start = System.currentTimeMillis();
// 执行该拦截器的后一个拦截器
// 如果该拦截器后没有其他拦截器,则直接执行Action的被拦截方法
String result = invocation.invoke();
// 打印执行结束的时间
System.out.println(name + " 拦截器的动作---------" +
"执行完登录Action的时间为:" + new Date());
long end = System.currentTimeMillis();
System.out.println(name + " 拦截器的动作---------" +
"执行完该Action的时间为" + (end - start) + "毫秒");
return result;
}
}
小结一下: