首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Struts1 核心解析(四):ActionServlet 預加載機制深度剖析

     編輯:Java 相關知識

Struts 1 框架的啟動流程可劃分為兩大階段:預加載階段與執行階段。預加載階段發生在 Servlet 容器(如 Tomcat)啟動時,此時尚未進入具體的請求轉發邏輯。本文將深入剖析 ActionServlet 在預加載階段的核心初始化流程。

web.xml 中的關鍵配置

回顧 Struts 在 web.xml 中的 Servlet 定義:

<servlet>
  <servlet-name>action</servlet-name>
  <servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
  <init-param>
    <param-name>config</param-name>
    <param-value>/WEB-INF/struts-config.xml</param-value>
  </init-param>
  <init-param>
    <param-name>debug</param-name>
    <param-value>2</param-value>
  </init-param>
  <init-param>
    <param-name>detail</param-name>
    <param-value>2</param-value>
  </init-param>
  <load-on-startup>2</load-on-startup>
</servlet>
<servlet-mapping>
  <servlet-name>action</servlet-name>
  <url-pattern>*.do</url-pattern>
</servlet-mapping>

<load-on-startup>2</load-on-startup> 指示容器在啟動時實例化並初始化該 Servlet。數值大於 0 即代表啟動時加載;為了方便調試,開發階段常將其改為 0 以延遲加載。

核心入口:init() 方法

經調試發現,init() 方法執行完畢即標誌著 Struts 預加載階段結束。以下是其簡化邏輯:

public void init() throws ServletException {
    try {
        initInternal();           // 初始化內部資源文件 ActionResources.properties
        initOther();              // 設定 struts-config.xml 路徑、註冊 ConvertUtils 轉換器
        initServlet();            // 讀取 web.xml 配置、獲取部署資訊
        getServletContext().setAttribute(Globals.ACTION_SERVLET_KEY, this);
        initModuleConfigFactory(); // 初始化模組配置工廠
        
        // 初始化預設模組(無前綴)
        ModuleConfig moduleConfig = initModuleConfig("", config);
        initModuleMessageResources(moduleConfig);
        initModuleDataSources(moduleConfig);
        initModulePlugIns(moduleConfig);
        moduleConfig.freeze();
        
        // 初始化帶前綴的模組(config/ 開頭的參數)
        Enumeration names = getServletConfig().getInitParameterNames();
        while (names.hasMoreElements()) {
            String name = (String) names.nextElement();
            if (!name.startsWith("config/")) continue;
            String prefix = name.substring(6);
            moduleConfig = initModuleConfig(prefix, getServletConfig().getInitParameter(name));
            initModuleMessageResources(moduleConfig);
            initModuleDataSources(moduleConfig);
            initModulePlugIns(moduleConfig);
            moduleConfig.freeze();
        }
        
        this.initModulePrefixes(this.getServletContext()); // 將所有前綴存入 ServletContext
        this.destroyConfigDigester(); // 釋放解析器資源
    } catch (UnavailableException ex) {
        throw ex;
    } catch (Throwable t) {
        log.error("Unable to initialize Struts ActionServlet...", t);
        throw new UnavailableException(t.getMessage());
    }
}

關鍵輔助方法解析

initInternal()

載入框架內部資源束 ActionResources.properties,提供國際化訊息支援。

initOther()

核心任務:

  • 確定 struts-config.xml 路徑(預設 /WEB-INF/struts-config.xml)
  • 註冊 ConvertUtils 基礎類型轉換器(BigDecimal、BigInteger 等),為表單數據自動類型轉換奠基

initServlet()

解析 web.xml 中的 <init-param>,獲取 Servlet 映射路徑、除錯等級等部署資訊。

模組化配置初始化

Struts 1.1+ 支援多模組。代碼分兩步走:

  1. 預設模組:對應 config 參數指定的配置文件,產生無前綴的 ModuleConfig 物件。
  2. 擴展模組:遍歷 config/ 開頭的初始化參數,每個參數對應一個獨立模組,產生帶前綴的 ModuleConfig(前綴為 config/ 後的字串)。

每個模組均初始化 MessageResources(國際化)、DataSource(資料源)、PlugIn(擴充套件),最後呼叫 freeze() 鎖定配置防止運行期修改。

initModulePrefixes() & destroyConfigDigester()

  • initModulePrefixes():將所有模組前綴彙總為字串陣列存入 ServletContext,供運行期路由查找。
  • destroyConfigDigester():將解析器 configDigester 置空,釋放記憶體。

初始化時序圖

Struts1 ActionServlet 初始化時序圖

預加載階段完成後,Struts 已備妥所有配置元數據,靜待請求進入執行階段。後續請求處理流程請參閱《層層遞進Struts1(五)之處理流程》。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved