博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
struts2源码分析之流程
阅读量:4705 次
发布时间:2019-06-10

本文共 6921 字,大约阅读时间需要 23 分钟。

本文想通过分析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 request23 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 will28             // return above and flow through again29             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 to46                 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

你可能感兴趣的文章
Linux内核分析— —操作系统是如何工作的(20135213林涵锦)
查看>>
圆角效果
查看>>
还原AdventureWorks2008示例数据库遇到的问题
查看>>
Java学习笔记--集合
查看>>
控件置顶[置顶] Android常用UI控件之ProgressBar
查看>>
FPGA 相同模块 VIVADO synthesis综合后
查看>>
Python 常用库(随时补充)
查看>>
android中如何获取xml界面里的非自定义属性
查看>>
vmware错误汇总
查看>>
[转载]H3C S3600 DHCP-SERVER 配置【原创】
查看>>
创建一个名为User的类
查看>>
Java Web-----JSP与Servlet(一)
查看>>
Java递归应用
查看>>
vue angular 分别实现分页
查看>>
在DataTable 中增加一列
查看>>
动态执行linq 语句 NLinq
查看>>
等待自己慢慢的蜕变
查看>>
BigDecimal四舍五入保留两位小数
查看>>
python类方法、类属性和静态方法
查看>>
[转]MySQL常用Json函数和MySQL常用字符串函数
查看>>