层层递进Struts1(四)之预加载ActionServlet

来源:互联网 发布:花生壳域名绑定公网ip 编辑:程序博客网 时间:2024/05/14 18:13

    Struts的执行相当于分为两个阶段,预加载阶段和执行阶段,预加载阶段是指在Tomcat启动之时就开始执行的内容,而此时我们并未真正进入跳转逻辑,这篇博客我们来分析一下预加载阶段。

配置文件

    还记得web.xml中关于Struts的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>  <!-- Standard Action Servlet Mapping -->  <servlet-mapping>    <servlet-name>action</servlet-name>    <url-pattern>*.do</url-pattern>  </servlet-mapping>

    其中<load-on-startup>2</load-on-startup>指的就是在Tomcat启动之时即执行,实际只要数字大于0,意思就是Tomcat启动即执行,为了进入调试,我们把这里改为0。
<load-on-startup>0</load-on-startup>

主函数init()

    经过调试发现,当执行完此函数,Struts的预加载阶段即结束,所以我们主要来看这个函数即可。

    /**     * <p>Initialize this servlet.  Most of the processing has been factored into     * support methods so that you can override particular functionality at a     * fairly granular level.</p>     *     * @exception ServletException if we cannot configure ourselves correctly     */    public void init() throws ServletException {        // Wraps the entire initialization in a try/catch to better handle        // unexpected exceptions and errors to provide better feedback        // to the developer        try {            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();        } catch (UnavailableException ex) {            throw ex;        } catch (Throwable t) {            // The follow error message is not retrieved from internal message            // resources as they may not have been able to have been             // initialized            log.error("Unable to initialize Struts ActionServlet due to an "                + "unexpected exception or error thrown, so marking the "                + "servlet as unavailable.  Most likely, this is due to an "                + "incorrect or missing library dependency.", t);            throw new UnavailableException(t.getMessage());        }        }

    很明显init函数中执行有其它函数,为了简明扼要,这些函数的代码不再完全照搬,碰到重要或是经典的代码片段我会放进来。

调用函数

    initInternal()

     此函数的作用是,初始化内部文件ActionResources.properties。

    initOther()

    此函数的作用是:指定struts-config.xml的路径,默认为/WEB-INF/struts-config.xml;同时注册ConvertUtils的数据类型,例如:

            ConvertUtils.register(new BigDecimalConverter(null), BigDecimal.class);            ConvertUtils.register(new BigIntegerConverter(null), BigInteger.class);

    initServlet()

    此函数的作用是:读取struts在web.xml中的配置信息,例如do/action、url等;获取web程序部署信息。

    与ModuleConfig相关

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();            }

    这段代码的作用是,将web.xml中的Struts配置文件初始化为ModuleConfig对象,将struts-config中的MessageResource、DataSource、PlugIn也都初始化为对象,保存到ServletContext中。不同的是,while循环外操作的是web.xml里 ActionServlet配置中config初始化参数指定的Struts配置文件;while循环内操作的是web.xml里 ActionServlet配置中以"config/"开头的初始化参数指定的Struts配置文件,这样的区别造成前者会产生没有前缀的ModuleConfig对象到ServletConfig中,后者会产生带前缀的ModuleConfig对象放到ServletContext中,前缀为“config/”后的字符串。

    initModulePrefixes(this.getServletContext());

    此函数的作用是将循环产生的所有前缀生成一个String数组,放到ServletContext中。

    destroyConfigDigester();

    此函数的作用是将ActionServlet类的configDigester的值改为为null。

执行顺序图

    

    这篇文章主要是分析了在Tomcat启动时struts的预处理情况,在struts执行逻辑处理时是如何处理的,请看我的博客《层层递进Struts1(五)之处理流程》。

    更多相关博客,请至《层层递进Struts1(八)之总结》。

原创粉丝点击