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

    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(八)之总结》

  • 7
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 17
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 17
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值