Struts2 源码的解析(12)

首先需要建立Struts2 HelloWorld,然后再使用eclipse的debug功能查看Struts2的源码。

当一个请求到来时会经过Struts2Filter过滤(调用其中的doFilter)。

①.Struts2的request处理流程如下:

Struts2 源码的解析(12)_第1张图片
下面我们来看看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.设置端点的位置如下:

Struts2 源码的解析(12)_第2张图片
 B.查看debug视图:

Struts2 源码的解析(12)_第3张图片
 从上的debug视图,我们可以看到详细的方法调用过程

 

你可能感兴趣的:(struts2)