当一个请求发出时,由StrutsPrepareAndExecuteFilter过滤请求。它会调用Dispatcher来处理请求,Dispatcher类会执行serviceAction方法,创建ActionProxy,并调用ActionProxy的execute()方法。ActionProxy的execute()方法会调用ActionInvocation的invoke()方法。
public String invoke() throws Exception {
String profileKey = "invoke: ";
try {
UtilTimerStack.push(profileKey);
if (executed) {
throw new IllegalStateException("Action has already executed");
}
if (interceptors.hasNext()) { //1判断拦截器链是否有下一个
//2
final InterceptorMapping interceptor = (InterceptorMapping) interceptors.next();
String interceptorMsg = "interceptor: " + interceptor.getName();
UtilTimerStack.push(interceptorMsg);
try {
resultCode = interceptor.getInterceptor().intercept(DefaultActionInvocation.this); // 3调用拦截器intercept方法,并把当前引用传给拦截器
}finally {
UtilTimerStack.pop(interceptorMsg);
}
} else {
resultCode = invokeActionOnly(); // 4当拦截器链中不存在下一个拦截器时,调用action
}
if (!executed) { // 5如果没有执行过拦截器或action的结果
if (preResultListeners != null) { // 6如果有前置结果监听器则,则在结果执行前调用
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(); // 7执行结果
}
executed = true; // 8执行标志改为true
}
return resultCode; // 9
} finally {
UtilTimerStack.pop(profileKey);
}
}
假如有拦截器i1和i2。拦截testAction的execute()方法,示意代码如下:
i1
public String intercept(ActionInvocation invocation) throws Exception {
System.out.println("i1 Start!");
String result = invocation.invoke();
System.out.println("i1 End!");
return "i1result";
i2
public String intercept(ActionInvocation invocation) throws Exception {
System.out.println("i2 Start!");
String result = invocation.invoke();
System.out.println("i2 End!");
return "i2result";
}
testAction
public String execute() throws Exception {
System.out.println(“execute()”);
return “success”
}
ActionProxy调用ActionInvocation的invoke()方法。
执行//1代码,返回true。
执行//2代码,返回i1的拦截器映射。
执行//3代码,调用i1的interceptor()方法,并且把当前ActionInvocation对象传递给interceptor()方法。
执行i1的interceptor()方法,输出i1 Start。
i1中调用ActionInvocation的invoke()方法,开始第一次递归调用。
执行//1代码,返回true。
执行//2代码,返回i2的拦截器映射对象。
执行//3代码,调用i2的interceptor()方法,并且把当前ActionInvocation对象传递给interceptor()方法。
执行i2的interceptor()方法,输出i2 Start。
i2中调用ActionInvocation的invoke()方法,开始第二次递归调用。
执行//1代码,返回false。
执行//4代码,调用目标Action的execute()方法。把返回值赋给resultCode。
执行//5代码,executed默认为false,所以!executed为true。
执行//6代码,因为没有结果监听器,所以返回false。
执行//7代码,执行result。通过resultCode获取物理页面!
执行//8代码,设置executed为true,表示已经处理结果。
执行//9代码,返回resultCode到i2的interceptor()。
i2输出i2 End。
i2返回i2result,程序流程回到ActionInvocation的invoke()方法的//3位置。
因为这时executed已经为true,所以invoke()方法直接返回i2result,即i2的返回值。
流程返回到i1,i1输出i1 End。
i1返回i1result,程序流程回到ActionInvocation的invoke()方法的//3位置。
因为这时executed已经为true,所以invoke()方法直接返回i1result,即i1的返回值。
程序流程返回到ActionProxy的execute()方法。
如果i1中没有调用invocation.invoke方法,而是直接返回result,那么i2就不会被执行,而返回结果会变成i1返回的result;如果正常情况下调用了invoke方法,则i1、i2返回的result不会对最终结果造成影响,最终返回的将是action的result。
具体流程图如下: