struts1源码分析(二)初始化主线

在Struts1整体概览和核心组件一文中,我们提到了Struts1框架的两条主线:初始化主线和请求处理主线,本文将探寻Struts1框架初始化这条主线。本文使用的Struts版本为1.2.8, 不同版本会略有差异,1.3.x系列对请求处理进行优化,差异性将另文叙述。

[问题]

在介绍初始化过程之前,我们先来思考几个问题。

1. 如何在web应用中植入框架的初始化过程?

2. 如何便捷地读取框架配置文件,完成配置文件到Java对象的映射?

3. 哪些组件需要完成初始化,如果完成?

4. 如何存储初始化阶段的成果?

[初始化入口]

在上文中我们提到,Struts1框架的入口和核心是ActionServlet类。通常在web.xml中会有如下配置:

<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>
</servlet>

<servlet-mapping>
    <servlet-name>action</servlet-name>
    <url-pattern>*</url-pattern>
</servlet-mapping>

上述配置可以看出,所有的请求都交由ActionServlet进行处理。ActionServlet本身作为一个Servlet(继承HttpServlet),自然符合Servlet的生命周期,容器在调用service()方法处理请求之前,需要提前调用init()方法完成Servlet初始化工作。init()方法在Servlet生命周期中只会被调用一次。由于Servlet生命周期中的这些特性,使得框架的初始化入口一般都在init()方法中。其他框架也不例外,比如SpringMVC,框架初始化交由DispatcherServlet的init()方法完成。

[初始化概览]

从整体上先预览一下init()方法:

public void init() throws ServletException {

    // 此处省略了方法前后的异常处理
    // 第一阶段,准备阶段
    initInternal();
    initOther();
    initServlet();
    
    // 第二阶段, 默认模块配置解析
    getServletContext().setAttribute(Globals.ACTION_SERVLET_KEY, this);
    initModuleConfigFactory();
    // Initialize modules as needed
    ModuleConfig moduleConfig = initModuleConfig("", config);

    // 第三阶段,默认模块组件初始化
    initModuleMessageResources(moduleConfig);
    initModuleDataSources(moduleConfig);
    initModulePlugIns(moduleConfig);
    moduleConfig.freeze();

    // 第四阶段, 自定义模块初始化
    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());
    this.destroyConfigDigester();

}
 这里将初始化过程分为五个阶段,通过分析每个阶段做了那些事来解读整个初始化过程。下面简要介绍一下每个阶段所做的工作。

相关推荐