zoukankan      html  css  js  c++  java
  • 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     }

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

  • 相关阅读:
    FreeRTOS之源码 及 移植详解
    FreeRTOS之Tracealyzer for FreeRTOS(FreeRTOS+Trace) 详解(源码解析+移植)
    FreeRTOS之全配置项详解、裁剪(FreeRTOSConfig.h)
    linux下安装oracle中遇到的一些问题
    RedHat Enterprise Linux 6 配置Xmanager ,实现图形界面连接
    Linux ext2/ext3文件系统详解
    对固态硬盘ssd进行4k对齐
    在CentOs6.5安装jdk
    Android的API版本和名称对应关系
    Java反射机制及Method.invoke详解
  • 原文地址:https://www.cnblogs.com/huashui/p/3175656.html
Copyright © 2011-2022 走看看