Struts 1 框架的啟動流程可劃分為兩大階段:預加載階段與執行階段。預加載階段發生在 Servlet 容器(如 Tomcat)啟動時,此時尚未進入具體的請求轉發邏輯。本文將深入剖析 ActionServlet 在預加載階段的核心初始化流程。
回顧 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() 方法執行完畢即標誌著 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());
}
}
載入框架內部資源束 ActionResources.properties,提供國際化訊息支援。
核心任務:
struts-config.xml 路徑(預設 /WEB-INF/struts-config.xml)ConvertUtils 基礎類型轉換器(BigDecimal、BigInteger 等),為表單數據自動類型轉換奠基解析 web.xml 中的 <init-param>,獲取 Servlet 映射路徑、除錯等級等部署資訊。
Struts 1.1+ 支援多模組。代碼分兩步走:
config 參數指定的配置文件,產生無前綴的 ModuleConfig 物件。config/ 開頭的初始化參數,每個參數對應一個獨立模組,產生帶前綴的 ModuleConfig(前綴為 config/ 後的字串)。每個模組均初始化 MessageResources(國際化)、DataSource(資料源)、PlugIn(擴充套件),最後呼叫 freeze() 鎖定配置防止運行期修改。
initModulePrefixes():將所有模組前綴彙總為字串陣列存入 ServletContext,供運行期路由查找。destroyConfigDigester():將解析器 configDigester 置空,釋放記憶體。
預加載階段完成後,Struts 已備妥所有配置元數據,靜待請求進入執行階段。後續請求處理流程請參閱《層層遞進Struts1(五)之處理流程》。