struts2的啓動流程與請求流程

從點擊服務器(這裏說到的服務器爲tomcat)的start來啓動服務,到對服務器發出請求,中間經歷了一個怎樣的過程?

啓動流程:
WEB服務器啓動:
1- 加載解析 $CATALINA_HOME/conf/web.xml
2-加載每個WEB app 下的 web.xml
3-對於struts2框架,在web.xml中,會配置攔截器,如下。這時候會初始化 StrutsPrepareAndExecuteFilter類

<filter>
        <filter-name>struts2</filter-name>
        <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>struts2</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

4-在StrutsPrepareAndExecuteFilter類中的init方法中初始化struts2的配置文件:

public void init(FilterConfig filterConfig) throws ServletException {
        InitOperations init = new InitOperations();
        Dispatcher dispatcher = null;
        try {
            FilterHostConfig config = new FilterHostConfig(filterConfig); 
            init.initLogging(config);  //日誌相關
            dispatcher = init.initDispatcher(config);//配置文件初始化
            init.initStaticContentLoader(config, dispatcher);

            prepare = new PrepareOperations(dispatcher);
            execute = new ExecuteOperations(dispatcher);
            this.excludedPatterns = init.buildExcludedPatternsList(dispatcher);

            postInit(dispatcher, filterConfig);
        } finally {
            if (dispatcher != null) {
                dispatcher.cleanUpAfterInit();
            }
            init.cleanup();
        }
    }

5:跟蹤代碼,在Dispatcher類中的init方式中,初始化具體的配置文件

public void init() {

        if (configurationManager == null) {
            configurationManager = createConfigurationManager(DefaultBeanSelectionProvider.DEFAULT_BEAN_NAME);
        }

        try {
            init_FileManager();
            init_DefaultProperties(); // [1] 
            init_TraditionalXmlConfigurations(); // [2]
            init_LegacyStrutsProperties(); // [3]
            init_CustomConfigurationProviders(); // [5]
            init_FilterInitParameters() ; // [6]
            init_AliasStandardObjects() ; // [7]

            Container container = init_PreloadConfiguration();
            container.inject(this);
            init_CheckWebLogicWorkaround(container);

            if (!dispatcherListeners.isEmpty()) {
                for (DispatcherListener l : dispatcherListeners) {
                    l.dispatcherInitialized(this);
                }
            }
            errorHandler.init(servletContext);

        } catch (Exception ex) {
            if (LOG.isErrorEnabled())
                LOG.error("Dispatcher initialization failed", ex);
            throw new StrutsException(ex);
        }
    }

[1] – init_DefaultProperties()
位置:struts-core-2.3.32.jar -> org/apache/struts2/default.properties
作用:用於配置Struts2常量的默認值

[2]–init_TraditionalXmlConfigurations()
這裏會初始話三個配置文件:

 private static final String DEFAULT_CONFIGURATION_PATHS = "struts-default.xml,struts-plugin.xml,struts.xml";

即:struts-default.xml,struts-plugin.xml,struts.xml

  • struts-default.xml
    位置: struts-core-2.3.32.jar 類路徑的根路徑下
    作用:Struts2核心配置

  • struts-plugin.xml
    作用:strut2插件的配置文件

  • struts.xml
    位置:用戶類路徑的根路徑 /src
    作用:用戶編寫的業務處理映射(Action)

[3]–init_LegacyStrutsProperties()
位置:用戶類路徑的根路徑 /src
作用:配置Struts2的常量(非必須)

[5]–init_CustomConfigurationProviders()
用於配置 struts.custom.properties
位置:用戶類路徑的根路徑 /src
作用:配置用戶自定義常量

啓動流程小結:

  • 加載解析 $CATALINA_HOME/conf/web.xml(tomcat)
  • 初始化 StrutsPrepareAndExecuteFilter
  • 然後按序加載下面配置文件
  • default.properties,
  • struts-default.xml, struts-plugin.xml,struts.xml,
  • struts.properties,
  • struts.custom.properties


請求流程
當求服務器發出請求的時候,首先會被StrutsPrepareAndExecuteFilter類的doFilter方法攔截:

public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {

        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) res;
        try {
            if (excludedPatterns != null && prepare.isUrlExcluded(request, excludedPatterns)) {
                chain.doFilter(request, response);
            } else {
                prepare.setEncodingAndLocale(request, response);
                prepare.createActionContext(request, response); 
                prepare.assignDispatcherToThread();
                request = prepare.wrapRequest(request);
                ActionMapping mapping = prepare.findActionMapping(request, response, true);//獲取是否有相應的action
                if (mapping == null) { //對於靜態資源的處理
                    boolean handled = execute.executeStaticResourceRequest(request, response);
                    if (!handled) {
                        chain.doFilter(request, response);
                    }
                } else {
                    //有相應的action時
                    execute.executeAction(request, response, mapping);
                }
            }
        } finally {
            prepare.cleanupRequest(request);
        }
    }

然後調用響應的攔截器:

if (interceptors.hasNext()) { //這裏會被反覆的調用,直到所有的攔截器都被調用完,然後執行相應的action方法
                final InterceptorMapping interceptor = interceptors.next();
                String interceptorMsg = "interceptor: " + interceptor.getName();
                UtilTimerStack.push(interceptorMsg);
                try {
                                resultCode = interceptor.getInterceptor().intercept(DefaultActionInvocation.this);
                            }
                finally {
                    UtilTimerStack.pop(interceptorMsg);
                }
            } else {
                resultCode = invokeActionOnly();
            }
發佈了76 篇原創文章 · 獲贊 48 · 訪問量 9萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章