拦截器原理模拟
首先,让我们来看看struts的interceptor运行过程,如图:
从这个图我们可以清楚的看到,doFilter调用Dispatcher中的serviceAction方法ValueStack stack = (ValueStack) request.getAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY);得到值栈中的值并且创建了ActionProxy并且调用execute方法,而ActionProxy则调用ActionInvocation中的invoke方法,ActionInvocation又调用了exceptionInterceptor中的interceptor方法,而exceptionInterceptor又反过来调用了ActionInvocation中的invoke方法,直到所有的interceptor都已执行,最后才调用TestAction中的execute方法。
我们模拟代码如下,首先建立一个Interceptor接口:
public interface Interceptor {
public void intercept(ActionInvocation invocation);
}
然后建立两个interceptor来实现这个接口,FirstInterceptor代码如下:
public class FirstInterceptor implements Interceptor{
public void intercept(ActionInvocation invocation) {
System.out.println(1);
invocation.invoke();
System.out.println(-1);
}
}
SecondInterceptor代码如下:
public class SecondInterceptor implements Interceptor{
public void intercept(ActionInvocation invocation) {
System.out.println(2);
invocation.invoke();
System.out.println(-2);
}
}
然后建立一个ActionInvocation类代码如下:
public class ActionInvocation {
List<Interceptor> interceptors = new ArrayList<Interceptor>();
int index = -1;
Action a = new Action();
public ActionInvocation(){
this.interceptors.add(new FirstInterceptor());
this.interceptors.add(new SecondInterceptor());
}
public void invoke(){
index++;
if(index>=this.interceptors.size()){
a.execute();
}else{
this.interceptors.get(index).intercept(this);
}
}
}
从代码中可以看到,invoke方法中反复从List中取出Interceptor对象并调用它的intercept方法,直到所有的都调用完毕才调用Action的execute方法。
其中Action的代码如下:
public class Action {
public void execute(){
System.out.println("execute!");
}
}