简单模拟了下Struts2拦截器的原理。
首先定义Interceptor接口:
package com.kaso.interceptor;
public interface Interceptor {
public String intercept(ActionInvocation invocation);
}
该接口中引用了ActionInvocation类:
package com.kaso.interceptor;
import java.util.ArrayList;
import java.util.List;
public class ActionInvocation {
private List<Interceptor> interceptors = new ArrayList<Interceptor>();
private int index = -1;
private String resultCode;
private Action action;
public String invoke() {
index++;
if (index < interceptors.size()) {
resultCode = interceptors.get(index).intercept(this);
} else {
action.execute();
}
return resultCode;
}
public Action getAction() {
return action;
}
public void setAction(Action action) {
this.action = action;
}
public List<Interceptor> getInterceptors() {
return interceptors;
}
public void setInterceptors(List<Interceptor> interceptors) {
this.interceptors = interceptors;
}
}
在ActionInvocation类中,有一个interceptor的集合属性,一个用于遍历的下标,一个结果,一个Action。为集合和action提供了getter和setter方法。在invoke方法中,首先判断是否存在下一个监听器,如果存在则调用interceptor的intercept方法,如果不存在则调用action的execute方法。
package com.kaso.interceptor;
public class Action {
public String execute() {
System.out.println("execute() in Action");
return "success";
}
}
写两个Interceptor的实现类:
package com.kaso.interceptor.impl;
import com.kaso.interceptor.ActionInvocation;
import com.kaso.interceptor.Interceptor;
public class MyInterceptor1 implements Interceptor {
@Override
public String intercept(ActionInvocation invocation) {
System.out.println(1);
String result = invocation.invoke();
System.out.println(-1);
return result;
}
}
package com.kaso.interceptor.impl;
import com.kaso.interceptor.ActionInvocation;
import com.kaso.interceptor.Interceptor;
public class MyInterceptor2 implements Interceptor {
@Override
public String intercept(ActionInvocation invocation) {
System.out.println(2);
String result = invocation.invoke();
System.out.println(-2);
return result;
}
}
在interceptor中的intercept方法又会调用invocation的invoke方法,从而形成递归调用。写一个ActionProxy类来测试:
package com.kaso.interceptor;
import java.util.ArrayList;
import java.util.List;
import com.kaso.interceptor.impl.MyInterceptor1;
import com.kaso.interceptor.impl.MyInterceptor2;
public class ActionProxy {
public static void main(String[] args) {
// 假设main为ActionProxy的execute方法
List<Interceptor> interceptors = new ArrayList<Interceptor>();// 创建拦截器链
interceptors.add(new MyInterceptor1());
interceptors.add(new MyInterceptor2());
ActionInvocation invocation = new ActionInvocation();
invocation.setInterceptors(interceptors);// 设置拦截器链
invocation.setAction(new Action());// 设置Action
invocation.invoke();// 调用invoke方法
}
}
当执行了invocation.invoke方法后,会首先查找list中是否存在下一个interceptor。找到MyInterceptor1,调用intercept方法,首先输出“1”,然后再调用invocation.invoke方法。继续查找到MyInterceptor2,查找到后调用intercept方法,然后输出“2”,再调用invocation的invoke方法。这次拦截器链中的拦截器已经调用完毕,则调用Action的execute方法,并输出“execute() in Action”,然后返回到invoke方法中。invoke方法再返回到MyInterceptor2的intercept方法中,并输出“-2”,然后继续返回到invoke方法中。invoke方法再返回到MyInterceptor1的intercept方法中,并输出“-1”,最终返回到ActionProxy中。本模拟没有对resultCode进行处理。
最后输出结果:
1
2
execute() in Action
-2
-1