拦截器,是struts最具特色的,也是被大家称赞的亮点之一,整个拦截器体系运用了AOP思想,流程由责任链模式完成。
下面将对拦截器的源码进行部分解读
struts2通过创建代理对象,由生成的代理action走过拦截器的一系列流程
StrutsPrepareAndExecuteFilter的executeAction()方法
execute.executeAction(request, response, mapping);
略去中间调用的过程,直接进入拦截器的核心调度类DefaultActionInvocation
观察这个类,发现这个方法的参数,接受的是动态代理生成的引用
public void init(ActionProxy proxy) {
this.proxy = proxy;
Map contextMap = createContextMap();
// Setting this so that other classes, like object factories, can use the ActionProxy and other
// contextual information to operate
ActionContext actionContext = ActionContext.getContext();
if (actionContext != null) {
actionContext.setActionInvocation(this);
}
//根据代理对象,创建action的代理实例,底层是根据反射实现的
createAction(contextMap);
if (pushAction) {
//把action压入栈顶
stack.push(action);
//将action存入上下文
contextMap.put("action", action);
}
invocationContext = new ActionContext(contextMap);
invocationContext.setName(proxy.getActionName());
// get a new List so we don't get problems with the iterator if someone changes the list
//获取全部的拦截器,将其存入集合之中,ArrayList,并迭代
List interceptorList = new ArrayList(proxy.getConfig().getInterceptors());
interceptors = interceptorList.iterator();
}
invoke()方法,也是这个DefaultActionInvocation的核心类,整个拦截器的调用过程都时在这个方法中实现的。
public String invoke() throws Exception {
String profileKey = "invoke: ";
try {
//压栈
UtilTimerStack.push(profileKey);
if (executed) {
throw new IllegalStateException("Action has already executed");
}
if (interceptors.hasNext()) {
final InterceptorMapping interceptor = interceptors.next();
String interceptorMsg = "interceptor: " + interceptor.getName();
UtilTimerStack.push(interceptorMsg);
try {
//返回String类型的resultCode,因为最后的preResultCode和Result都是String类型
//递归调用,执行拦截器链中的拦截器
resultCode = interceptor.getInterceptor().intercept(DefaultActionInvocation.this);
}
finally {
UtilTimerStack.pop(interceptorMsg);
}
} else {
resultCode = invokeActionOnly();
}
// this is needed because the result will be executed, then control will return to the Interceptor, which will
// return above and flow through again
if (!executed) {
if (preResultListeners != null) {
for (Object preResultListener : preResultListeners) {
PreResultListener listener = (PreResultListener) preResultListener;
String _profileKey = "preResultListener: ";
try {
UtilTimerStack.push(_profileKey);
listener.beforeResult(this, resultCode);
}
finally {
UtilTimerStack.pop(_profileKey);
}
}
}
// now execute the result, if we're supposed to
if (proxy.getExecuteResult()) {
executeResult();
}
executed = true;
}
return resultCode;
}
finally {
UtilTimerStack.pop(profileKey);
}
}
在这里需要注意的是拦截执行的顺序
例:
Interceptor1
Interceptor2
action
preResultListener
Result
Interceptor2
Interceptor1
实现原理很简单,就是利用invoke的返回值调用的。
每一个拦截器都要事先Interceptor接口,接口很简单,初始化,销毁,和执行的intercepter方法,供invoke方法调用。
public interface Interceptor extends Serializable {
void destroy();
void init();
String intercept(ActionInvocation invocation) throws Exception;
}
PreResultListener 的加入实现方法,PreResultListener 的执行位置在action之后,rusult之前。
public void addPreResultListener(PreResultListener listener) {
if (preResultListeners == null) {
preResultListeners = new ArrayList(1);
}
preResultListeners.add(listener);
}
整个拦截器因为责任链模式,充分的完成了解耦,每一个拦截器互相都不知道对方的存在,同时,这样做,提高了扩展性,当想要给拦截器栈中加一个拦截器的时候,直接插入拦截器,方便快捷。