分析 Struts中的struts-config.xml解析过程

写在最前面:说实在的,这部分会有点难懂,我自己也觉得很困难来把它整个说清楚,涉及到的类和方法都太宠杂,只能尽力而为.

因为本文主要是讨论使用digester进行xml解析.所以不关注,整个ActionServlet 初始化的整个流程,我们把注意力集中在解析xml配置文件的那部分代码,但读者还是要对Servlet,和Struts的一些相关的知识有一定的了解,比如说Servlet的生命周期,Struts的配置文件中的元素组成结构以及各个标签的含意是什么.




4.1 introduction of  ActionServlet


    形象点说,ActionServlet是Struts世界中的接线员,负责接收所有的请求,并把这个请求,转发给合适的人(这里的人在Struts中就是Action类型的实例了.
        ActionServlet继承了,javax.servlet.http.HttpServlet.是个Servlet当然也就遵循Servlet的生命周期.
  
   我们这里复习一下Servlet的生命周期
               1.Servlet实例被创建.
               2. 调用init(ServletConfig config )方法.(在HttpServlet中实际上在init(ServletConfig config ) 中调用了init()所以我们可以覆盖 init()方法来进行初例化)
               3.接受客户请求.调用service方法.(在HttpServelt中,会调用doGet和doPost)
               4. 调用destroy()方法.
               5.实例被销毁.


   接着,我们看一下,ActionServlet在生命周期都做了些什么事情呢?


   init()方法
                     

在struts源码中我增加了相关的注释,并删除了异常处理的代码,希望大家能更容易理解^^

Java代码 复制代码
  1.      public void init() throws ServletException {   
  2.   
  3.             //初使化国际化相关的,MessageResource bundle   
  4.             initInternal();   
  5.                
  6.             //初使化我们这个controller servlet的字符转换函数   
  7.             initOther();   
  8.             //初使化web.xml中的信息.   
  9.             initServlet();   
  10.         //将ActionServlet实例以Globals.ACTION_SERVLET_KEY为key存在ServletContext对象中   
  11.             getServletContext().setAttribute(Globals.ACTION_SERVLET_KEY, this);   
  12.             initModuleConfigFactory();   
  13.             // Initialize modules as needed   
  14.                
  15.             //初使化,ModuleConfig这个moduleConfig相当重要,封装了所有的,struts-config.xml中的信息.   
  16.             //也就是我们解析struts-config.xml中的root元素了.一会我们将来看一下initModuleConfig中都做了些什么事情.   
  17.             ModuleConfig moduleConfig = initModuleConfig("", config);   
  18.                
  19.                 
  20.             //通过moduleConfig中的配置文件信息,创建MessageResource对象.   
  21.             initModuleMessageResources(moduleConfig);   
  22.             //通过moduleConfig中的配置文件信息,创建DataSource对象.   
  23.             initModuleDataSources(moduleConfig);   
  24.             //通过moduleConfig中的配置文件信息,创建   
  25.             initModulePlugIns(moduleConfig);   
  26.             //将配置文件中的各个对象,设置成已配置状态.   
  27.             moduleConfig.freeze();   
  28.   
  29. Enumeration names = getServletConfig().getInitParameterNames();   
  30.                
  31.             //通过web.xml的中参数配置,得到其它的Struts的配置文件并以上面的方式对,moduleConfig进行同样的配置   
  32.             while (names.hasMoreElements()) {   
  33.                 String name = (String) names.nextElement();   
  34.                 if (!name.startsWith("config/")) {   
  35.                     continue;   
  36.                 }   
  37.                 String prefix = name.substring(6);   
  38.                 moduleConfig = initModuleConfig   
  39.                     (prefix, getServletConfig().getInitParameter(name));   
  40.                 initModuleMessageResources(moduleConfig);   
  41.                 initModuleDataSources(moduleConfig);   
  42.                 initModulePlugIns(moduleConfig);   
  43.                 moduleConfig.freeze();   
  44.             }   
  45.        
  46.             this.initModulePrefixes(this.getServletContext());   
  47.             this.destroyConfigDigester();   
  48.          
  49.     }  
 	 public void init() throws ServletException {

        	//初使化国际化相关的,MessageResource bundle
            initInternal();
            
            //初使化我们这个controller servlet的字符转换函数
            initOther();
            //初使化web.xml中的信息.
            initServlet();
        //将ActionServlet实例以Globals.ACTION_SERVLET_KEY为key存在ServletContext对象中
            getServletContext().setAttribute(Globals.ACTION_SERVLET_KEY, this);
            initModuleConfigFactory();
            // Initialize modules as needed
            
            //初使化,ModuleConfig这个moduleConfig相当重要,封装了所有的,struts-config.xml中的信息.
            //也就是我们解析struts-config.xml中的root元素了.一会我们将来看一下initModuleConfig中都做了些什么事情.
            ModuleConfig moduleConfig = initModuleConfig("", config);
            
             
            //通过moduleConfig中的配置文件信息,创建MessageResource对象.
            initModuleMessageResources(moduleConfig);
            //通过moduleConfig中的配置文件信息,创建DataSource对象.
            initModuleDataSources(moduleConfig);
            //通过moduleConfig中的配置文件信息,创建
            initModulePlugIns(moduleConfig);
            //将配置文件中的各个对象,设置成已配置状态.
            moduleConfig.freeze();

Enumeration names = getServletConfig().getInitParameterNames();
            
            //通过web.xml的中参数配置,得到其它的Struts的配置文件并以上面的方式对,moduleConfig进行同样的配置
            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();
      
    }


由上面的代码可以看出,在init方法中,Struts对很的信息进行了初使化,并使用,
ModuleConfig moduleConfig = initModuleConfig("", config)方法得到了struts-config.xml中的信息,所以解析配置文件的具体的方法也就是在这个方法里面完成的了.我们将在一会详细讲解一下这个方法的代码.


doGet  以及  doPost方法.
将请求委托给
process(request, response);方法.
我们再来看一下process方法又做了些什么呢?

Java代码 复制代码
  1. protected void process(HttpServletRequest request, HttpServletResponse response)   
  2.        throws IOException, ServletException {   
  3.   
  4.        ModuleUtils.getInstance().selectModule(request, getServletContext());   
  5.        ModuleConfig config = getModuleConfig(request);   
  6.               
  7.        //通过config对象来得来一个RequestProcessor对象(第一次请求的时候,为空的,).   
  8.        RequestProcessor processor = getProcessorForModule(config);   
  9.        if (processor == null) {   
  10.          //如果还没有配置一个RequestProcessor对象,就会通过,config对象来生成一个,默认就为org.apache.struts.action.RequestProcessor可以被扩展.   
  11.           processor = getRequestProcessor(config);   
  12.        }   
  13.        /**  
  14.            通过processor来转发处理请求.(无非是通过请求的路径,以及config对象来生成  
  15.              ActionMapping BeanForm 以及,具体的Action实例,和 ActionForward)  
  16.          然后调用得到的Action bean的execute方法  
  17.         */  
  18.        processor.process(request, response);   
  19.    }  
 protected void process(HttpServletRequest request, HttpServletResponse response)
        throws IOException, ServletException {

        ModuleUtils.getInstance().selectModule(request, getServletContext());
        ModuleConfig config = getModuleConfig(request);
            
        //通过config对象来得来一个RequestProcessor对象(第一次请求的时候,为空的,).
        RequestProcessor processor = getProcessorForModule(config);
        if (processor == null) {
          //如果还没有配置一个RequestProcessor对象,就会通过,config对象来生成一个,默认就为org.apache.struts.action.RequestProcessor可以被扩展.
           processor = getRequestProcessor(config);
        }
        /**
            通过processor来转发处理请求.(无非是通过请求的路径,以及config对象来生成
              ActionMapping BeanForm 以及,具体的Action实例,和 ActionForward)
          然后调用得到的Action bean的execute方法
         */
        processor.process(request, response);
    }


所有的请求最终都是通过,ActionServelt 的process方法中被RequestProcessor来处理的,
RequestProcessor通过ModuleConfig对象里的信息,以前客户端的请求的路径,分别得到,在配置文件中所配置的,Action  bean的实例, ActionMapping的信息,ActionForward的信息,以及,可以所配置的FormBean的信息.然后调用  Action   bean 实例的execute方法来完成整个请求.


最后再来看destory方法

Java代码 复制代码
  1. public void destroy() {   
  2.   
  3.        
  4.     /**  
  5.      * 和 init()方 法 相 对 应 ,做 了 相 关 的 清 理 工 作 ,具 体 的 ,读 者 可 以 参 见 init()方 法   
  6.      */  
  7.         if (log.isDebugEnabled()) {   
  8.             log.debug(internal.getMessage("finalizing"));   
  9.         }   
  10.   
  11.         destroyModules();   
  12.         destroyInternal();   
  13.         getServletContext().removeAttribute(Globals.ACTION_SERVLET_KEY);   
  14.   
  15.         // Release our LogFactory and Log instances (if any)   
  16.         ClassLoader classLoader = Thread.currentThread().getContextClassLoader();   
  17.         if (classLoader == null) {   
  18.             classLoader = ActionServlet.class.getClassLoader();   
  19.         }   
  20.      
  21.             LogFactory.release(classLoader);   
  22.       
  23.   
  24.         PropertyUtils.clearDescriptors();   
  25.   
  26.     }  
public void destroy() {

    
    /**
     * 和 init()方 法 相 对 应 ,做 了 相 关 的 清 理 工 作 ,具 体 的 ,读 者 可 以 参 见 init()方 法 
     */
        if (log.isDebugEnabled()) {
            log.debug(internal.getMessage("finalizing"));
        }

        destroyModules();
        destroyInternal();
        getServletContext().removeAttribute(Globals.ACTION_SERVLET_KEY);

        // Release our LogFactory and Log instances (if any)
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        if (classLoader == null) {
            classLoader = ActionServlet.class.getClassLoader();
        }
  
            LogFactory.release(classLoader);
   

        PropertyUtils.clearDescriptors();

    }


这一节,我们详细的介绍了ActionServlet的生命周期中各个阶段所做的事情.下一节,我们将专注于,initModuleConfig方法,看一下struts只解析xml文件的具体过程.





4.2   concentrate   on the method of    initModuleConfig 

上一节,我们讲了ActionServlet的生命周期,其中有一个方法进入了我们的视野.
  ModuleConfig moduleConfig = initModuleConfig("", config) ,在这一节中我们将要仔细分析这个方法的源代码,
当然为了更容易理解,我将删除掉struts中源码的一部分,只保留核心那部分代码..

Java代码 复制代码
  1. protected ModuleConfig initModuleConfig(String prefix, String paths)   
  2.        throws ServletException {   
  3.   
  4.        // Parse the configuration for this module   
  5.        ModuleConfigFactory factoryObject = ModuleConfigFactory.createFactory();   
  6.           
  7.          
  8.        /**  
  9.        通过prefix的值来创建ModuleConfig对象  
  10.        这里的prefix的含意是,模块名称,使用过struts的朋友可能有这个印象,在struts中,如果配置多个配置文件,是要在.  
  11.        web.xml中指定的路径是 config/name/***.xml 这里的name就是prefix了.^^  
  12.           <init-param>  
  13.            <param-name>config/name</param-name>  
  14.            <param-value>/WEB-INF/struts-config.xml</param-value>  
  15.        </init-param>  
  16.         如这个web.xml中的配置中的, name/即为模块的prefix  
  17.         */  
  18.        ModuleConfig config = factoryObject.createModuleConfig(prefix);   
  19.   
  20.        // Configure the Digester instance we will use   
  21.        //初使化并,得到Digester对象(在初使化的过程中一定会添加各种监听,我们一会将看一下初使化的具体代码)   
  22.        Digester digester = initConfigDigester();   
  23.   
  24.   
  25.  // Process each specified resource path   
  26.        //配 置 文 件 的 路 径 名 的 字 符 串 ,可 以 指 定 多 个 配 置 文 件 的 路 径 ,以  ','  间 隔 .   
  27.        //这 里 将 迭 代 解 析 每 一 个 路 径 下 的 配 置 文 件    
  28.   
  29.        while (paths.length() > 0) {   
  30.            digester.push(config);   
  31.            String path = null;   
  32.            int comma = paths.indexOf(',');   
  33.            if (comma >= 0) {   
  34.                path = paths.substring(0, comma).trim();   
  35.                paths = paths.substring(comma + 1);   
  36.            } else {   
  37.                path = paths.trim();   
  38.                paths = "";   
  39.            }   
  40.   
  41.            if (path.length() < 1) {   
  42.                break;   
  43.            }   
  44.   
  45.   
  46. //将 解 析 的 具 体 操 作 委 托 给 parseModuleConfigFile方 法    
  47.   
  48.            this.parseModuleConfigFile(digester, path);   
  49.        }   
  50.   
  51.   
  52.   
  53. //将 所 得 到 的 ModuleConfig对 象 以 org.apache.struts.action.MODULE为 key放 进  ServletContext对 象 中 去    
  54.        //以 方 便 以 后 的 使 用    
  55.   
  56.        getServletContext().setAttribute(   
  57.            Globals.MODULE_KEY + config.getPrefix(),   
  58.            config);   
  59.        return config;   
  60.    }   
  61.   
  62.    
 protected ModuleConfig initModuleConfig(String prefix, String paths)
        throws ServletException {

        // Parse the configuration for this module
        ModuleConfigFactory factoryObject = ModuleConfigFactory.createFactory();
        
       
        /**
        通过prefix的值来创建ModuleConfig对象
        这里的prefix的含意是,模块名称,使用过struts的朋友可能有这个印象,在struts中,如果配置多个配置文件,是要在.
        web.xml中指定的路径是 config/name/***.xml 这里的name就是prefix了.^^
           <init-param>
            <param-name>config/name</param-name>
            <param-value>/WEB-INF/struts-config.xml</param-value>
        </init-param>
         如这个web.xml中的配置中的, name/即为模块的prefix
         */
        ModuleConfig config = factoryObject.createModuleConfig(prefix);

        // Configure the Digester instance we will use
        //初使化并,得到Digester对象(在初使化的过程中一定会添加各种监听,我们一会将看一下初使化的具体代码)
        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;
            }


 //将 解 析 的 具 体 操 作 委 托 给 parseModuleConfigFile方 法 

            this.parseModuleConfigFile(digester, path);
        }



 //将 所 得 到 的 ModuleConfig对 象 以 org.apache.struts.action.MODULE为 key放 进  ServletContext对 象 中 去 
        //以 方 便 以 后 的 使 用 

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

  





整个方法中很明确,首先,通过,initConfigDigester();方法来得到一个,已经被设置了各种监听的Digester对象,然后将path路径下的xml 文件进行解析.那么,到底设置了哪些监听规则呢?我们来跟到initConfigDigester()方法中看一下.
(源码的版本依然被我阉割了,以便于大家理解.)

Java代码 复制代码
  1. protected Digester initConfigDigester() throws ServletException {   
  2.   
  3.     //是否已经存在解析好了的configDigester对象了,如果是直接返回.   
  4.       if (configDigester != null) {   
  5.           return (configDigester);   
  6.       }   
  7.   
  8.       // Create a new Digester instance with standard capabilities   
  9.       //创建一个新的Digester对象,并设置参数   
  10.       configDigester = new Digester();   
  11.       //名字是否空间敏感.   
  12.       configDigester.setNamespaceAware(true);   
  13.       //设置是否验证XML文档有效   
  14.       configDigester.setValidating(this.isValidating());   
  15.       //设置是否使用上下文的ClassLoader(通过,Thread.currentThread().getContextClassLoader()得到的)来加载   
  16.       //为digester对象设置的监听类   
  17.       configDigester.setUseContextClassLoader(true);   
  18.       //为digester对象来填加监听类集合   
  19.       configDigester.addRuleSet(new ConfigRuleSet());   
  20.       // Return the completely configured Digester instance   
  21.       return (configDigester);   
  22.   }  
  protected Digester initConfigDigester() throws ServletException {
 
    	//是否已经存在解析好了的configDigester对象了,如果是直接返回.
        if (configDigester != null) {
            return (configDigester);
        }

        // Create a new Digester instance with standard capabilities
        //创建一个新的Digester对象,并设置参数
        configDigester = new Digester();
        //名字是否空间敏感.
        configDigester.setNamespaceAware(true);
        //设置是否验证XML文档有效
        configDigester.setValidating(this.isValidating());
        //设置是否使用上下文的ClassLoader(通过,Thread.currentThread().getContextClassLoader()得到的)来加载
        //为digester对象设置的监听类
        configDigester.setUseContextClassLoader(true);
        //为digester对象来填加监听类集合
        configDigester.addRuleSet(new ConfigRuleSet());
        // Return the completely configured Digester instance
        return (configDigester);
    }



从这个方法中,我们可以看到,具体的匹配规则是通过,一个叫ConfigRuleSet()的对象传进来的.
我们接着考查,到底这个ConfigRuleSet()是个啥鬼东西^^.
这个类大约有五百行大小,为了方便,我们在这里讲解,我们只截取其中的一部分,但这也足够大家理解了.


Java代码 复制代码
  1.   
  2.   
  3.   
  4. public class ConfigRuleSet extends RuleSetBase {   
  5.   
  6.    public void addRuleInstances(Digester digester) {   
  7.     //步骤一   
  8.  digester.addRule   
  9.             ("struts-config/action-mappings",   
  10.              new SetActionMappingClassRule());   
  11.     //步骤二   
  12.         digester.addFactoryCreate   
  13.             ("struts-config/action-mappings/action",   
  14.              new ActionMappingFactory());   
  15.     //步骤三   
  16.         digester.addSetProperties   
  17.             ("struts-config/action-mappings/action");   
  18.     //步骤四   
  19.         digester.addSetNext   
  20.             ("struts-config/action-mappings/action",   
  21.              "addActionConfig",   
  22.              "org.apache.struts.config.ActionConfig");   
  23.      //步骤五   
  24.         digester.addSetProperty   
  25.             ("struts-config/action-mappings/action/set-property",   
  26.              "property""value");   
  27.   
  28.        }   
  29.   
  30.   
  31. final class SetActionMappingClassRule extends Rule {   
  32.   
  33.     public  SetActionMappingClassRule() {   
  34.         super();   
  35.     }   
  36.   
  37.     public void begin(String namespace, String name, Attributes attributes) throws Exception {   
  38.         String className = attributes.getValue("type");   
  39.         if (className != null) {   
  40.             ModuleConfig mc = (ModuleConfig) digester.peek();   
  41.             mc.setActionMappingClass(className);   
  42.         }   
  43.     }   
  44.   
  45. }   
  46.   
  47. final class ActionMappingFactory extends AbstractObjectCreationFactory {   
  48.   
  49.     public Object createObject(Attributes attributes) {   
  50.   
  51.         // Identify the name of the class to instantiate   
  52.        String className = attributes.getValue("className");   
  53.         if (className == null) {   
  54.             ModuleConfig mc = (ModuleConfig) digester.peek();   
  55.             className = mc.getActionMappingClass();   
  56.         }   
  57.   
  58.         // Instantiate the new object and return it   
  59.         Object actionMapping = null;   
  60.         try {   
  61.             actionMapping =   
  62.                 RequestUtils.applicationInstance(className);   
  63.         } catch (Exception e) {   
  64.             digester.getLogger().error(   
  65.                     "ActionMappingFactory.createObject: ", e);   
  66.         }   
  67.   
  68.         return actionMapping;   
  69.     }   
  70.   
  71. }   
  72.   
  73.  }  

public class ConfigRuleSet extends RuleSetBase {

   public void addRuleInstances(Digester digester) {
    //步骤一
 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");

       }


final class SetActionMappingClassRule extends Rule {

    public  SetActionMappingClassRule() {
        super();
    }

    public void begin(String namespace, String name, Attributes attributes) throws Exception {
        String className = attributes.getValue("type");
        if (className != null) {
            ModuleConfig mc = (ModuleConfig) digester.peek();
            mc.setActionMappingClass(className);
        }
    }

}

final class ActionMappingFactory extends AbstractObjectCreationFactory {

    public Object createObject(Attributes attributes) {

        // Identify the name of the class to instantiate
       String className = attributes.getValue("className");
        if (className == null) {
            ModuleConfig mc = (ModuleConfig) digester.peek();
            className = mc.getActionMappingClass();
        }

        // Instantiate the new object and return it
        Object actionMapping = null;
        try {
            actionMapping =
                RequestUtils.applicationInstance(className);
        } catch (Exception e) {
            digester.getLogger().error(
                    "ActionMappingFactory.createObject: ", e);
        }

        return actionMapping;
    }

}

 }



下面我们就按照代码中注释的五个步骤一步一步分析.

步骤一.  digester.addRule
            ("struts-config/action-mappings",
             new SetActionMappingClassRule());
当解析的时候碰到<action-mappings>标签时,调用下面的方法

Java代码 复制代码
  1. public void begin(String namespace, String name, Attributes attributes) throws Exception {   
  2.         String className = attributes.getValue("type");   
  3.         if (className != null) {   
  4.             ModuleConfig mc = (ModuleConfig) digester.peek();   
  5.             mc.setActionMappingClass(className);   
  6.         }   
  7.     }  
public void begin(String namespace, String name, Attributes attributes) throws Exception {
        String className = attributes.getValue("type");
        if (className != null) {
            ModuleConfig mc = (ModuleConfig) digester.peek();
            mc.setActionMappingClass(className);
        }
    }

我们看到它将取得<action-mappings >
标签中的type元素的值并把它设置给配置文件的Root元素ModuleConfig的actionMappingClass,这个域的值默认为
org.apache.struts.action.ActionMapping

步骤二,   digester.addFactoryCreate
            ("struts-config/action-mappings/action",
             new ActionMappingFactory());
当遇到<action>标签时,将使用ActionMappingFactory类的createObject方法来创建一个对象.

Java代码 复制代码
  1. public Object createObject(Attributes attributes) {   
  2.   
  3.        // Identify the name of the class to instantiate   
  4.       String className = attributes.getValue("className");   
  5.        if (className == null) {   
  6.            ModuleConfig mc = (ModuleConfig) digester.peek();   
  7.            className = mc.getActionMappingClass();   
  8.        }   
  9.   
  10.        // Instantiate the new object and return it   
  11.        Object actionMapping = null;   
  12.        try {   
  13.            actionMapping =   
  14.                RequestUtils.applicationInstance(className);   
  15.        } catch (Exception e) {   
  16.            digester.getLogger().error(   
  17.                    "ActionMappingFactory.createObject: ", e);   
  18.        }   
  19.   
  20.        return actionMapping;   
  21.    }  
 public Object createObject(Attributes attributes) {

        // Identify the name of the class to instantiate
       String className = attributes.getValue("className");
        if (className == null) {
            ModuleConfig mc = (ModuleConfig) digester.peek();
            className = mc.getActionMappingClass();
        }

        // Instantiate the new object and return it
        Object actionMapping = null;
        try {
            actionMapping =
                RequestUtils.applicationInstance(className);
        } catch (Exception e) {
            digester.getLogger().error(
                    "ActionMappingFactory.createObject: ", e);
        }

        return actionMapping;
    }


通过,<action > 标签中的className属性来创建对象,当这个className没有指定时,使用默认的
org.apache.struts.action.ActionMapping类来创建对象.




步骤三.    digester.addSetProperties
            ("struts-config/action-mappings/action");
当碰到<action>标签时,使用<action >标签中的属性来设置  ActionMapping对象.
主要包括path, type,scope,validate等 这样我们就可以看到,所有的关于bean的配置信息实际都是放在了
ActionMapping对象中了.

步骤四. digester.addSetNext
            ("struts-config/action-mappings/action",
             "addActionConfig",
             "org.apache.struts.config.ActionConfig");
我们知道,整个xml文件的解析的项层对象是一个ModuleConfig对象,那么上面的这个方法的意思就是说,
当碰到<action>标签的时候,我们把生成 的ActionMapping对象,通过调用ModuleConfig对象的addActionConfig方法设置给root对象.
看一下,addActionConfig方法的具体实现.

Java代码 复制代码
  1. public void addActionConfig(ActionConfig config) {   
  2.   
  3.       if (configured) {   
  4.           throw new IllegalStateException("Configuration is frozen");   
  5.       }   
  6.       config.setModuleConfig(this);   
  7.   
  8.     //通过ActionMapping中的path为key,以ActionMapping对象为值放入actionConfigs这个Map中   
  9.       actionConfigs.put(config.getPath(), config);   
  10.       actionConfigList.add(config);   
  11.   
  12.   }  
  public void addActionConfig(ActionConfig config) {

        if (configured) {
            throw new IllegalStateException("Configuration is frozen");
        }
        config.setModuleConfig(this);

      //通过ActionMapping中的path为key,以ActionMapping对象为值放入actionConfigs这个Map中
        actionConfigs.put(config.getPath(), config);
        actionConfigList.add(config);

    }


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

       }
要使用action-mappings/action/set-property,需要编写ActionMapping子类,并给action-mappings 标签加上type属性,属性值就是我们编写的字类。这样当action的execute享有客户操作时将得到我们编写的ActionMapping事例。

我们编写的ActionMapping要具有action-mappings/action/set-property所设置的所有属性。如果action-mappings/action拥有set-property子标签,那么execute方法获得的ActionMapping事例就拥有set-property所设置的属性值。
一般来讲我们都不会自己来扩展ActionMapping类,也就使得这个方法不是特别重要.


4.3 小节
   通过上一节,我们分析了ActionMapping的解析过程,当然在struts配置文件中,其它部分的解析方式实际上都是同这个类似的,大家完全可以举一反三的去看它的源代码.(重复性劳动没有啥意义SO.)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值