struts2源码分析之流程

本文想通过分析struts2的源码来理解官方的流程图。

官方流程图如下:

流程步骤如下:

(1),首先根据web.xml的配置,当启动server时,会调用org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter过滤器的init()方法。

 1     public void init(FilterConfig filterConfig) throws ServletException {
 2         // 初始化InitOperations对象
 3         InitOperations init = new InitOperations();
 4         // 定义Dispatcher
 5         Dispatcher dispatcher = null;
 6         try {
 7             // 初始化FilterHostConfig对象
 8             FilterHostConfig config = new FilterHostConfig(filterConfig);
 9             // 初始化struts2的log工具
10             init.initLogging(config);
11             // 初始化dispatcher实例
12             dispatcher = init.initDispatcher(config);
13             init.initStaticContentLoader(config, dispatcher);
14 
15             prepare = new PrepareOperations(filterConfig.getServletContext(), dispatcher);
16             execute = new ExecuteOperations(filterConfig.getServletContext(), dispatcher);
17             this.excludedPatterns = init.buildExcludedPatternsList(dispatcher);
18 
19             postInit(dispatcher, filterConfig);
20         } finally {
21             if (dispatcher != null) {
22                 dispatcher.cleanUpAfterInit();
23             }
24             init.cleanup();
25         }
26     }

(2),初始化完成之后,根据浏览器访问地址,开始调用StrutsPrepareAndExecuteFilter的doFilter()方法

 1 public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
 2 
 3         HttpServletRequest request = (HttpServletRequest) req;
 4         HttpServletResponse response = (HttpServletResponse) res;
 5 
 6         try {
 7             // 设置request的encoding以及response的locale属性 
 8             prepare.setEncodingAndLocale(request, response);
 9             // 创建ActionContext对象
10             prepare.createActionContext(request, response);
11             // 将dispatcher绑定到ThreadLocal上
12             prepare.assignDispatcherToThread();
13             if (excludedPatterns != null && prepare.isUrlExcluded(request, excludedPatterns)) {
14                 chain.doFilter(request, response);
15             } else {
16                 request = prepare.wrapRequest(request);
17                 // 创建ActionMapping对象
18                 ActionMapping mapping = prepare.findActionMapping(request, response, true);
19                 if (mapping == null) {
20                     boolean handled = execute.executeStaticResourceRequest(request, response);
21                     if (!handled) {
22                         chain.doFilter(request, response);
23                     }
24                 } else {
25                     // 去执行对应的Action类
26                     execute.executeAction(request, response, mapping);
27                 }
28             }
29         } finally {
30             prepare.cleanupRequest(request);
31         }
32     }

(3),具体调用方法是在Dispatcher类的serviceAction()方法中:

 1  UtilTimerStack.push(timerKey);
 2 String namespace = mapping.getNamespace();
 3 String name = mapping.getName();
 4 String method = mapping.getMethod();
 5 
 6 Configuration config = configurationManager.getConfiguration();
 7 // 创建ActionProxy实例
 8 ActionProxy proxy = config.getContainer().getInstance(ActionProxyFactory.class).createActionProxy(
 9 namespace, name, method, extraContext, true, false);
10 
11 request.setAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY, proxy.getInvocation().getStack());
12 
13 // if the ActionMapping says to go straight to a result, do it!
14 if (mapping.getResult() != null) {
15 Result result = mapping.getResult();
16 result.execute(proxy.getInvocation());
17 } else {
18 // 调用对应的Action方法
19 proxy.execute();
20 }
21 
22 // If there was a previous value stack then set it back onto the request
23 if (!nullStack) {
24 request.setAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY, stack);
25 }

(4),接下来去DefaultActionProxy类中执行execute()方法:

 1 public String execute() throws Exception {
 2         ActionContext nestedContext = ActionContext.getContext();
 3         ActionContext.setContext(invocation.getInvocationContext());
 4 
 5         String retCode = null;
 6 
 7         String profileKey = "execute: ";
 8         try {
 9             UtilTimerStack.push(profileKey);
10             // 此处再调用DefaultActionInvocation类的invoke方法
11             retCode = invocation.invoke();
12         } finally {
13             if (cleanupContext) {
14                 ActionContext.setContext(nestedContext);
15             }
16             UtilTimerStack.pop(profileKey);
17         }
18 
19         return retCode;
20     }

(5),执行DefaultActionInvocation类的invoke方法:

 1  public String invoke() throws Exception {
 2         String profileKey = "invoke: ";
 3         try {
 4             UtilTimerStack.push(profileKey);
 5 
 6             if (executed) {
 7                 throw new IllegalStateException("Action has already executed");
 8             }
 9 
10             // 此处先开始执行拦截器,只要拦截器链还没执行完,就会一直执行
11             // 此invoke方法
12             if (interceptors.hasNext()) {
13                 final InterceptorMapping interceptor = interceptors.next();
14                 String interceptorMsg = "interceptor: " + interceptor.getName();
15                 UtilTimerStack.push(interceptorMsg);
16                 try {
17                                 resultCode = interceptor.getInterceptor().intercept(DefaultActionInvocation.this);
18                             }
19                 finally {
20                     UtilTimerStack.pop(interceptorMsg);
21                 }
22             } else {
23                 // 当所有拦截器都执行完成之后,执行invokeActionOnly()方法。
24                 resultCode = invokeActionOnly();
25             }
26 
27             // this is needed because the result will be executed, then control will return to the Interceptor, which will
28             // return above and flow through again
29             if (!executed) {
30                 if (preResultListeners != null) {
31                     for (Object preResultListener : preResultListeners) {
32                         PreResultListener listener = (PreResultListener) preResultListener;
33 
34                         String _profileKey = "preResultListener: ";
35                         try {
36                             UtilTimerStack.push(_profileKey);
37                             listener.beforeResult(this, resultCode);
38                         }
39                         finally {
40                             UtilTimerStack.pop(_profileKey);
41                         }
42                     }
43                 }
44 
45                 // now execute the result, if we're supposed to
46                 if (proxy.getExecuteResult()) {
47                     // 此处返回对应的result结果给客户端
48                     executeResult();
49                 }
50 
51                 executed = true;
52             }
53 
54             return resultCode;
55         }
56         finally {
57             UtilTimerStack.pop(profileKey);
58         }
59     }

目前粗略地看了一下大体上的流程,具体还要继续分析里面的各种设计模式,设计思想。

原文地址:https://www.cnblogs.com/huashui/p/3175656.html