首先需要建立Struts2 HelloWorld,然后再使用eclipse的debug功能查看Struts2的源码。
当一个请求到来时会经过Struts2Filter过滤(调用其中的doFilter)。
①.Struts2的request处理流程如下:
下面我们来看看struts2的部分源码:
1.StrutsPrepareAndExecuteFilter的doFilter方法
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
try {
prepare.setEncodingAndLocale(request, response);
prepare.createActionContext(request, response);
prepare.assignDispatcherToThread();
if ( excludedPatterns != null && prepare.isUrlExcluded(request, excludedPatterns)) {
chain.doFilter(request, response);
} else {
request = prepare.wrapRequest(request);
ActionMapping mapping = prepare.findActionMapping(request, response, true);
if (mapping == null) {
boolean handled = execute.executeStaticResourceRequest(request, response);
if (!handled) {
chain.doFilter(request, response);
}
} else {
execute.executeAction(request, response, mapping);//调用ExecuteOperations的executeAction方法
}
}
} finally {
prepare.cleanupRequest(request);
}
}
2.DefaultActionInvocation中的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()) {//判断是不是还有下一个InterceptorMapping,每个InterceptorMapping里面存放着一个Interceptor
final InterceptorMapping interceptor = interceptors.next();//获取下一个InterceprorMapping
String interceptorMsg = "interceptor: " + interceptor.getName();//获取interceptor的名字
UtilTimerStack.push(interceptorMsg);
try {
//得到Interceptor实例,然后在调用该实例的intercept方法,DefaultActionInvocation自己作参数
resultCode = interceptor.getInterceptor().intercept(DefaultActionInvocation.this);
}
finally {
UtilTimerStack.pop(interceptorMsg);
}
} else {//如果interceptors中没有了IntercetorMapping,说明所有的interceptor都调用完了。
//当调用完所有的interceptor之后,再调用action,在里面使用了反射调用了action中的方法
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);
}
}
3.随便找一个interceptor的,这个以ExceptionMappingInterceptor为例,查看其中的部分源码:
public String intercept(ActionInvocation invocation) throws Exception {
String result;
try {
//调用DefaultActionInvocation的invoke方法
result = invocation.invoke();
} catch (Exception e) {
if (isLogEnabled()) {
handleLogging(e);
}
//获取struts.xml配置文件中配置的Exception Mapping,返回的是一个List
List<ExceptionMappingConfig> exceptionMappings = invocation.getProxy().getConfig().getExceptionMappings();
//在集合List中是否存在action抛出这个异常,如果存在,返回Exception Mapping 对应result
String mappedResult = this.findResultFromExceptions(exceptionMappings, e);
if (mappedResult != null) {//看result是否为null
result = mappedResult;
publishException(invocation, new ExceptionHolder(e));//把异常的信息放入Value Stack中
} else {
throw e;
}
}
return result;
}
②.在DefaultActionInvocation中设置一个端点,在debug视图(显示方法执行流)查看详细的调用流程图
A.设置端点的位置如下:
B.查看debug视图:
从上的debug视图,我们可以看到详细的方法调用过程