`
文鸯
  • 浏览: 305677 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
社区版块
存档分类
最新评论

Struts源码学习 — 初始化ModuleConfig

阅读更多

Struts版本——1.2.9

Digester版本——1.6

 

 

初始化ModuleConfig就是指Struts将struts-config.xml初始化为ModuleConfig对象,实现这个动作的代码在ActionServlet的init()方法中,如下:

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

实际上,初始化ModuleConfig对象的过程仅仅在第3行的那句代码里,这里之所以列出这么多代码,是因为这段代码所做的事情可看成一个整体。对于这段代码的概括描述可参见Struts源码学习 — ActionServlet的初始化

 

 

将第3行代码里的initModuleConfig()方法挖开,如下:

    /**
     * <p>Initialize the module configuration information for the
     * specified module.</p>
     *
     * @param prefix Module prefix for this module
     * @param paths Comma-separated list of context-relative resource path(s)
     *  for this modules's configuration resource(s)
     *
     * @exception ServletException if initialization cannot be performed
     * @since Struts 1.1
     */
    protected ModuleConfig initModuleConfig(String prefix, String paths)
        throws ServletException {

        // :FIXME: Document UnavailableException? (Doesn't actually throw anything)

        if (log.isDebugEnabled()) {
            log.debug(
                "Initializing module path '"
                    + prefix
                    + "' configuration from '"
                    + paths
                    + "'");
        }

        // Parse the configuration for this module
        ModuleConfigFactory factoryObject = ModuleConfigFactory.createFactory();
        ModuleConfig config = factoryObject.createModuleConfig(prefix);

        // Configure the Digester instance we will use
        Digester digester = initConfigDigester();

        // Process each specified resource path
        while (paths.length() > 0) {
            digester.push(config);
            String path = null;
            int comma = paths.indexOf(',');
            if (comma >= 0) {
                path = paths.substring(0, comma).trim();
                paths = paths.substring(comma + 1);
            } else {
                path = paths.trim();
                paths = "";
            }

            if (path.length() < 1) {
                break;
            }

            this.parseModuleConfigFile(digester, path);
        }

        getServletContext().setAttribute(
            Globals.MODULE_KEY + config.getPrefix(),
            config);

        // Force creation and registration of DynaActionFormClass instances
        // for all dynamic form beans we wil be using
        FormBeanConfig fbs[] = config.findFormBeanConfigs();
        for (int i = 0; i < fbs.length; i++) {
            if (fbs[i].getDynamic()) {
                fbs[i].getDynaActionFormClass();
            }
        }

        return config;
    }

 

首先27、28两行,创建ModuleConfigFactory对象,其默认的实现是org.apache.struts.config.impl.DefaultModuleConfigFactory,可在web.xml中通过设置ActionServlet的configFactory初始化参数来改变实现类。然后由ModuleConfigFactory创建ModuleConfig对象,DefaultModuleConfigFactory的实现就是new一个org.apache.struts.config.impl.ModuleConfigImpl的对象,以prefix为构造方法的参数。

 

然后初始化Digester对象(后面详细说)。

 

因为参数paths可以是以逗号为分隔符的,多个struts-config.xml文件的路径,所以接下来的循环是用Digester对象分别对这多个struts-config.xml文件进行解析,解析的过程会将每个struts-config.xml文件里的元素都初始化为相应的XXXConfig对象,并将这些对象装进之前创建的ModuleConfig对象里。

 

然后将这个ModuleConfig对象放到ServletContext里。

 

59-64行,这一段是检查struts-config.xml文件里的所有form-bean元素,如果其type属性指定的类是动态FormBean,即org.apache.struts.action.DynaActionForm类或它的子类,就初始化FormBeanConfig的dynaActionFormClass字段。

 

最重要的代码在31行的initConfigDigester()方法里,挖开如下:

    /**
     * <p>Create (if needed) and return a new <code>Digester</code>
     * instance that has been initialized to process Struts module
     * configuration files and configure a corresponding <code>ModuleConfig</code>
     * object (which must be pushed on to the evaluation stack before parsing
     * begins).</p>
     *
     * @exception ServletException if a Digester cannot be configured
     * @since Struts 1.1
     */
    protected Digester initConfigDigester() throws ServletException {

        // :FIXME: Where can ServletException be thrown?

        // Do we have an existing instance?
        if (configDigester != null) {
            return (configDigester);
        }

        // Create a new Digester instance with standard capabilities
        configDigester = new Digester();
        configDigester.setNamespaceAware(true);
        configDigester.setValidating(this.isValidating());
        configDigester.setUseContextClassLoader(true);
        configDigester.addRuleSet(new ConfigRuleSet());

        for (int i = 0; i < registrations.length; i += 2) {
            URL url = this.getClass().getResource(registrations[i+1]);
            if (url != null) {
                configDigester.register(registrations[i], url.toString());
            }
        }

        this.addRuleSets();

        // Return the completely configured Digester instance
        return (configDigester);
    }

 

这个方法初始化Digester对象,就是这个Digester将struts-config.xml解析为ModuleConfig对象的。

 

Digester类的完全限定名为org.apache.commons.digester.Digester,来自于Apache Commons Digester,它是一个将XML映射到Java对象的工具。该工具底层还是使用SAX来解析XML,只是它在SAX的基础上,提出了一个Rule的概念。所谓Rule,通俗的解释就是“当扫描XML遇到某些结点时要做的事情”。Digester类根据这些Rule来解析XML,因此,解析之前需要给Digester添加这些Rule,Digester类里定义了一系列方法用来直接添加Rule。

 

也可以将添加Rule的繁琐工作委托给RuleSet来做,然后Digester调用addRuleSet(RuleSet)方法就行了。上面代码的25行就是这样做的,如何将struts-config.xml解析为ModuleConfig对象的Rule就是在ConfigRuleSet类的addRuleInstances()方法里添加到Digester的,该方法代码如下:

    /**
     * <p>Add the set of Rule instances defined in this RuleSet to the
     * specified <code>Digester</code> instance, associating them with
     * our namespace URI (if any).  This method should only be called
     * by a Digester instance.  These rules assume that an instance of
     * <code>org.apache.struts.config.ModuleConfig</code> is pushed
     * onto the evaluation stack before parsing begins.</p>
     *
     * @param digester Digester instance to which the new Rule instances
     *  should be added.
     */
    public void addRuleInstances(Digester digester) {

        digester.addObjectCreate
            ("struts-config/data-sources/data-source",
             "org.apache.struts.config.DataSourceConfig",
             "className");
        digester.addSetProperties
            ("struts-config/data-sources/data-source");
        digester.addSetNext
            ("struts-config/data-sources/data-source",
             "addDataSourceConfig",
             "org.apache.struts.config.DataSourceConfig");

        digester.addRule
            ("struts-config/data-sources/data-source/set-property",
             new AddDataSourcePropertyRule());

        digester.addRule
            ("struts-config/action-mappings",
             new SetActionMappingClassRule());

        digester.addFactoryCreate
            ("struts-config/action-mappings/action",
             new ActionMappingFactory());
        digester.addSetProperties
            ("struts-config/action-mappings/action");
        digester.addSetNext
            ("struts-config/action-mappings/action",
             "addActionConfig",
             "org.apache.struts.config.ActionConfig");

        digester.addSetProperty
            ("struts-config/action-mappings/action/set-property",
             "property", "value");

        digester.addObjectCreate
            ("struts-config/action-mappings/action/exception",
             "org.apache.struts.config.ExceptionConfig",
             "className");
        digester.addSetProperties
            ("struts-config/action-mappings/action/exception");
        digester.addSetNext
            ("struts-config/action-mappings/action/exception",
             "addExceptionConfig",
             "org.apache.struts.config.ExceptionConfig");

        digester.addSetProperty
            ("struts-config/action-mappings/action/exception/set-property",
             "property", "value");

        digester.addFactoryCreate
            ("struts-config/action-mappings/action/forward",
             new ActionForwardFactory());
        digester.addSetProperties
            ("struts-config/action-mappings/action/forward");
        digester.addSetNext
            ("struts-config/action-mappings/action/forward",
             "addForwardConfig",
             "org.apache.struts.config.ForwardConfig");

        digester.addSetProperty
            ("struts-config/action-mappings/action/forward/set-property",
             "property", "value");

        digester.addObjectCreate
            ("struts-config/controller",
             "org.apache.struts.config.ControllerConfig",
             "className");
        digester.addSetProperties
            ("struts-config/controller");
        digester.addSetNext
            ("struts-config/controller",
             "setControllerConfig",
             "org.apache.struts.config.ControllerConfig");

        digester.addSetProperty
            ("struts-config/controller/set-property",
             "property", "value");

        digester.addRule
            ("struts-config/form-beans",
             new SetActionFormBeanClassRule());

        digester.addFactoryCreate
            ("struts-config/form-beans/form-bean",
             new ActionFormBeanFactory());
        digester.addSetProperties
            ("struts-config/form-beans/form-bean");
        digester.addSetNext
            ("struts-config/form-beans/form-bean",
             "addFormBeanConfig",
             "org.apache.struts.config.FormBeanConfig");

        digester.addObjectCreate
            ("struts-config/form-beans/form-bean/form-property",
             "org.apache.struts.config.FormPropertyConfig",
             "className");
        digester.addSetProperties
            ("struts-config/form-beans/form-bean/form-property");
        digester.addSetNext
            ("struts-config/form-beans/form-bean/form-property",
             "addFormPropertyConfig",
             "org.apache.struts.config.FormPropertyConfig");

        digester.addSetProperty
            ("struts-config/form-beans/form-bean/form-property/set-property",
             "property", "value");

        digester.addSetProperty
            ("struts-config/form-beans/form-bean/set-property",
             "property", "value");

        digester.addObjectCreate
            ("struts-config/global-exceptions/exception",
             "org.apache.struts.config.ExceptionConfig",
             "className");
        digester.addSetProperties
            ("struts-config/global-exceptions/exception");
        digester.addSetNext
            ("struts-config/global-exceptions/exception",
             "addExceptionConfig",
             "org.apache.struts.config.ExceptionConfig");

        digester.addSetProperty
            ("struts-config/global-exceptions/exception/set-property",
             "property", "value");

        digester.addRule
            ("struts-config/global-forwards",
             new SetActionForwardClassRule());

        digester.addFactoryCreate
            ("struts-config/global-forwards/forward",
             new GlobalForwardFactory());
        digester.addSetProperties
            ("struts-config/global-forwards/forward");
        digester.addSetNext
            ("struts-config/global-forwards/forward",
             "addForwardConfig",
             "org.apache.struts.config.ForwardConfig");

        digester.addSetProperty
            ("struts-config/global-forwards/forward/set-property",
             "property", "value");

        digester.addObjectCreate
            ("struts-config/message-resources",
             "org.apache.struts.config.MessageResourcesConfig",
             "className");
        digester.addSetProperties
            ("struts-config/message-resources");
        digester.addSetNext
            ("struts-config/message-resources",
             "addMessageResourcesConfig",
             "org.apache.struts.config.MessageResourcesConfig");

        digester.addSetProperty
            ("struts-config/message-resources/set-property",
             "property", "value");

        digester.addObjectCreate
            ("struts-config/plug-in",
             "org.apache.struts.config.PlugInConfig");
        digester.addSetProperties
            ("struts-config/plug-in");
        digester.addSetNext
            ("struts-config/plug-in",
             "addPlugInConfig",
             "org.apache.struts.config.PlugInConfig");

        digester.addRule
            ("struts-config/plug-in/set-property",
             new PlugInSetPropertyRule());

    }

 

这里的所有addXXX()方法都是在添加Rule,只不过其中不叫addRule的方法是添加Digester的内置Rule的便捷方法。所有方法的第一个参数都是一个XPath格式的String,这些String看着都很眼熟吧,没错,都是struts-config.xml里的。

 

先说说Digester是如何使用Rule来解析XML的,执行Digester类的parse()方法来扫描解析XML,当扫描XML遇到匹配某个XPath的标签,就开始使用Digester里对应于这个XPath的Rule。碰到开始标签时,调用Rule的begin()方法;标签如果有体,调用Rule的body()方法;碰到结束标签时,调用Rule的end()方法。如果对应于某个XPath有多个Rule,就有个调用顺序的问题了。对于begin()方法,是按照Rule添加到Digester里的顺序调用;end()方法调用顺序与begin()相反。这点跟栈的思想一样。

 

这段代码里使用到的一些Digester内置Rule有:

ObjectCreateRule:创建对象并压栈。

FactoryCreateRule:由工厂来创建对象并压栈。

SetPropertiesRule:将标签属性值设置到栈顶对象的属性里。

SetPropertyRule:设置栈顶对象的单个属性的值。

SetNextRule:调用栈顶第2个元素的指定方法来建立它和栈顶元素的关系。

 

一般对标签的处理方式是,先用ObjectCreateRule或FactoryCreateRule创建对象,然后用SetPropertiesRule或SetPropertyRule设置对象的属性值,最后用SetNextRule建立该标签和父标签的关系。上面的代码基本就是这个套路,另外还加入了一些Struts自定义的Rule,如下:

AddDataSourcePropertyRule:设置DataSource的属性。

PlugInSetPropertyRule:设置PlugIn的属性。

SetActionMappingClassRule:根据struts-config/action-mappings标签的type属性,设置ActionConfig的实现类。

SetActionFormBeanClassRule:根据struts-config/form-beans标签的type属性,设置FormBeanConfig的实现类。

SetActionForwardClassRule:根据struts-config/global-forwards标签的type属性,设置ForwardConfig的实现类。

 

对于ActionConfig、FormBeanConfig、ForwardConfig,有3种方式可以改变这3个XXXConfig的实现类。

1. 使用自定义的ModuleConfig实现类,在其中定义XXXConfig的实现类,这个改变影响范围最大,针对于整个应用的XXXConfig。Struts默认的ModuleConfig实现类是org.apache.struts.config.impl.ModuleConfigImpl,这个类里面定义了XXXConfig的默认实现类,分别是org.apache.struts.action.ActionMapping、org.apache.struts.action.ActionFormBean、org.apache.struts.action.ActionForward。

2. 象上面最后的3个Rule说明中提到的那样,设置type属性,这个改变只针对于单个struts-config.xml中的XXXConfig。

3. 具体到单个struts-config.xml中的单个XXXConfig配置,设置它的className属性,来改变单个XXXConfig的实现类,这个改变影响最小,只针对单个XXXConfig。

正因为它们的实现类可以这样灵活的改变,所以上面代码在为Digester添加创建它们实例的Rule时,使用的是FactoryCreateRule,而不是ObjectCreateRule。要构造一个FactoryCreateRule,需要为它提供一个ObjectCreationFactory,前者将创建对象的工作委托给后者。Struts提供了创建这3种Config对象的ObjectCreationFactory——ActionMappingFactory、ActionFormBeanFactory、ActionForwardFactory、GlobalForwardFactory。如果标签给出了className属性,这些Factory就以该属性值创建对象;如果没有,就以之前设置的实现类创建对象。

分享到:
评论
1 楼 xhsbetter 2009-01-13  
学习了

相关推荐

    struts源码学习.pdf

    通过对`struts源码学习.pdf`文件中的内容分析,我们可以深入了解Struts框架内部的工作原理,尤其是`RequestProcessor`类和`ModuleConfig`接口的关键作用。这些知识对于理解和优化基于Struts的应用程序至关重要,同时...

    Struts1.2源码解读

    接着,ModuleConfig的初始化是Struts配置的核心。ModuleConfig是一个容器,用于存放Struts应用的配置信息。在Struts应用运行时,所有的MessageResource、PlugIn、数据源等都是通过ModuleConfig来管理的。因此,...

    struts1.2源码研究

    - 初始化默认模块,解析配置文件,创建ModuleConfig对象,并处理动态Form对象。 - 初始化消息资源、数据源和插件信息。 - 设置configured属性为true,表明模块加载完成。 - 加载其他模块,重复上述步骤。 - ...

    Struts1源码解析

    4. `initModuleConfig()`方法将`struts-config.xml`中的配置项初始化后放入`moduleConfig`对象,以提高访问速度,因为`moduleConfig`存储在内存中,读取速度远超硬盘。 5. 插件初始化,Struts1支持插件机制,增强了...

    struts源码解析

    在Struts框架中,`init()`方法用于初始化ActionServlet,它会调用`initInternal()`以及其他必要的初始化操作,比如加载配置、注册事件监听器等。 5. **struts流程图方法图.vsd**: 这个文件可能是一个详细的流程图,...

    servlet+struts源码

    总的来说,深入学习Servlet和Struts的源码,不仅能够帮助开发者理解这两个组件的工作原理,还能提升他们的问题排查能力,以及进行更高效、更灵活的Java Web应用开发。通过实践和理解这些源码,你将能够更好地适应...

    struts-1.3.9 源码

    Struts是Apache软件基金会下的一个开源项目,是一个用于构建企业级Java Web应用程序的MVC(Model-View-Controller)框架。...对于想要深入理解Web开发和MVC模式的人来说,研究Struts的源码无疑是一个宝贵的学习资源。

    struts-1.2.9-src源码类库

    总的来说,"struts-1.2.9-src"源码库是学习和研究Struts框架的经典资料,通过阅读和分析,开发者可以更好地掌握Java Web开发,特别是Struts框架的应用技巧和内部机制,为实际项目开发提供坚实的理论基础和技术支持。

    Struts源代码阅读.CHM

    Struts 初始化 initInternal()方法: initOther()方法 initServlet()方法 getServletContext().setAttribute(Globals.ACTION_SERVLET_KEY, this) ModuleConfig moduleConfig = ...

    struts的入门学习

    - `init()`方法会加载`struts-config.xml`,创建`ModuleConfig`对象,加载资源文件,创建`MessageResources`对象,以及可能的数据源和`PlugIn`初始化。 2. **RequestProcessor**: - 处理每个子应用模块的请求,...

    strut培训--深入struts

    在初始化阶段,ActionServlet读取配置文件`struts-config.xml`,创建相应的ModuleConfig对象,存储Action、ControlConfig、FormBeanConfig、ForwardConfig和MessageResourcesConfig等配置信息。每个ModuleConfig代表...

    Struts模式培训资料 通过经典的实例 全面讲述Struts的开发运用

    在Struts中,ActionServlet作为控制器,负责接收HTTP请求,解析配置文件(struts-config.xml)并初始化ModuleConfig对象。ActionServlet根据请求找到对应的Action子类,如果找不到合适的Action,会直接将请求转发给...

    ModuleConfig.zip

    例如,初始化网络接口、设置网络参数(如IP地址、子网掩码、网关)或更新设备固件等。 为了充分利用`ModuleConfig.h`,开发者需要深入理解`ch9121`协议的规范,包括协议报文的结构、命令和响应格式,以及协议中的...

    struts面试题大全.doc

    - 初始化:ActionServlet读取配置文件,初始化ModuleConfig对象。 - 请求处理:接收HTTP请求,根据ActionConfig找到匹配的Action子类。 - 参数填充:ActionForm使用请求参数填充自身,可进行参数合法性验证。 - ...

    struts1.x面试题大全.pdf

    1. 控制器进行初始化工作,读取配置文件,为不同的 Struts 模块初始化相应的 ModuleConfig 对象。 2. 控制器接收 Http 请求,并从 ActionConfig 中找出对应于该请求的 Action 子类,如果没有对应的 Action,控制器...

    Struts配置文件详解

    Struts配置文件是Struts框架的灵魂所在,它不仅控制着框架的初始化流程,还决定着组件的创建与配置,极大提升了应用的灵活性与可扩展性。 **1.1 动态配置提升灵活性** Struts配置文件允许开发者在不修改代码的情况...

    Struts Controller UML diagrams

    这个示例的核心配置文件是`struts-config.xml`,它是Struts控制器初始化时解析的关键资源文件,用于分发映射信息到`ActionConfig`、`ForwardConfig`和`FormBeanConfig`实例中。 ### 类图分析 #### ...

    Struts配置文件详解.

    此外,`ConfigRuleSet`类负责解析配置文件,根据预定义的规则创建并初始化其他配置类的实例。 2. `&lt;struts-config&gt;`元素 `&lt;struts-config&gt;`是配置文件的根元素,对应于`ModuleConfig`类。它包含8个主要子元素,如`...

    struts2 配置文件

    - `&lt;init-param&gt;` 子元素: 配置初始化参数。 - `param-name`: 设置 `config` 参数名。 - `param-value`: 指定 `struts-config.xml` 的路径。 - **欢迎文件列表**: - `&lt;welcome-file-list&gt;` 元素: 指定一系列欢迎...

    知识共享-struts1.2配置文件详解(雷惊风).

    - `&lt;init-param&gt;` 元素用于设置servlet的初始化参数,其中 `config` 参数尤为重要,它指定了Struts框架配置文件(struts-config.xml)的相对路径,这是Struts ActionServlet专有的配置,确保Struts能够正确读取配置...

Global site tag (gtag.js) - Google Analytics