深入浅出学习Struts1框架(八):ActionServlet实例化之ModuleConfig

来源:互联网 发布:培训课程网络促销方案 编辑:程序博客网 时间:2024/05/18 11:45

上篇博客介绍了在ActionServlet的init方法实例化的时候完成的三个方法,主要是介绍了initInternal()方法、initOther()方法、initServlet()方法这三个方法。


       通过上篇博客的介绍我门知道initInternal()方法主要是创建资源类MessageResources的,比如说国际化资源等,具体这里可以见org.apache.struts.action下的ActionResources.properties文件;initOther()方法初始化其它的配置,获取我们自己的struts-config配置文件的路径,而它的默认路径就是web-inf/struts-config.xml,另外这个方法还会注册一些转换类的;而initServlet()方法就是主要利用digester来解析web.xml下的配置内容。


       今天将继续讲解init方法中做的其他的事情。首先说在说之前还是先讲init方法的具体实现代码写出来以便大家方便阅读和理解。


       Init源代码:

[java] view plaincopyprint?
  1. public void init() throws ServletException {  
  2.     
  3.   try {  
  4.         //初始化资源类  
  5.       initInternal();  
  6.       //注册转换类  
  7.       initOther();  
  8.       //利用digester读取web.xml文件并且将其放到servletContext中  
  9.       initServlet();  
  10.       getServletContext().setAttribute(Globals.ACTION_SERVLET_KEY, this);  
  11.         
  12.       initModuleConfigFactory();  
  13.       ModuleConfig moduleConfig = initModuleConfig("", config);  
  14.       initModuleMessageResources(moduleConfig);  
  15.       initModuleDataSources(moduleConfig);  
  16.       initModulePlugIns(moduleConfig);  
  17.       moduleConfig.freeze();  
  18.   
  19.       Enumeration names = getServletConfig().getInitParameterNames();  
  20.       while (names.hasMoreElements()) {  
  21.           String name = (String) names.nextElement();  
  22.           if (!name.startsWith("config/")) {  
  23.               continue;  
  24.           }  
  25.           String prefix = name.substring(6);  
  26.           moduleConfig = initModuleConfig  
  27.               (prefix, getServletConfig().getInitParameter(name));  
  28.           initModuleMessageResources(moduleConfig);  
  29.           initModuleDataSources(moduleConfig);  
  30.           initModulePlugIns(moduleConfig);  
  31.           moduleConfig.freeze();  
  32.       }  
  33.   
  34.       this.initModulePrefixes(this.getServletContext());  
  35.   
  36.       this.destroyConfigDigester();  
  37.   } catch (UnavailableException ex) {  
  38.       throw ex;  
  39.   } catch (Throwable t) {  
  40.       log.error("Unable to initialize Struts ActionServlet due to an "  
  41.           + "unexpected exception or error thrown, so marking the "  
  42.           + "servlet as unavailable.  Most likely, this is due to an "  
  43.           + "incorrect or missing library dependency.", t);  
  44.       throw new UnavailableException(t.getMessage());  
  45.   }      
  46. }  


        getServletContext().setAttribute(Globals.ACTION_SERVLET_KEY,this);这句话是将ActionServlet实例将以Globals.ACTION_SERVLET_KEY作为key存入servletcontext中。


       这里的Globals.ACTION_SERVLET_KEY在ActionServlet已经给出了声明:

[java] view plaincopyprint?
  1. public static final String ACTION_SERVLET_KEY=  
  2.         "org.apache.struts.action.ACTION_SERVLET";  

        接下来initModuleConfigFactory()方法,这个方法主要的作用是解析在web.xml中configFactory的text值。如果configFactory有配置,则将设置ModuleConfigFactory中得factoryClass值,否则默认得为               DefaultModuleConfigFactory。该方法其实宗旨是让开发人员自己开发出ModuleConfigFactory,从而得到自己所需要的ModuleConfig类。因为我们的实例中没有配置这个参数信息,所以我们这里的实例是要defalutModelConfigFactory了。


      代码段一:

[java] view plaincopyprint?
  1. protected voidinitModuleConfigFactory(){  
  2.         String configFactory =getServletConfig().getInitParameter("configFactory");  
  3.         if (configFactory != null) {  
  4.             ModuleConfigFactory.setFactoryClass(configFactory);  
  5.         }  
  6. }  

      代码段二:

[java] view plaincopyprint?
  1. public static void setFactoryClass(String factoryClass) {  
  2.         ModuleConfigFactory.factoryClass = factoryClass;  
  3.         ModuleConfigFactory.clazz = null;  
  4.     }  

     代码段三:

[java] view plaincopyprint?
  1. protected static String factoryClass =  
  2.         "org.apache.struts.config.impl.DefaultModuleConfigFactory";  
  3. }  

      ModuleConfig moduleConfig =initModuleConfig("", config)方法是非常重要的,initModuleConfig方法给strits-config里面的属性初始化后放入moduleConfig对象里面去,放到moduleConfig对象里面去便于以后操作更快,因为它是文件流。


     具体实现代码:

[java] view plaincopyprint?
  1. protected ModuleConfig initModuleConfig(Stringprefix, String paths)  
  2.         throws ServletException {  
  3.    
  4.         // :FIXME: Document UnavailableException? (Doesn't actually throw anything)  
  5.    
  6.         if (log.isDebugEnabled()) {  
  7.             log.debug(  
  8.                 "Initializing module path '"  
  9.                     + prefix  
  10.                     + "' configuration from '"  
  11.                     + paths  
  12.                     + "'");  
  13.         }  
  14.    
  15.         // Parse the configuration for this module  
  16.         ModuleConfigFactory factoryObject= ModuleConfigFactory.createFactory();  
  17.         ModuleConfig config =factoryObject.createModuleConfig(prefix);  
  18.    
  19.         // Configure the Digester instance we will use  
  20.         Digester digester =initConfigDigester();  
  21.    
  22.         // Process each specified resource path  
  23.         while (paths.length() > 0) {  
  24.             digester.push(config);  
  25.             String path = null;  
  26.             int comma = paths.indexOf(',');  
  27.             if (comma >= 0) {  
  28.                 path =paths.substring(0, comma).trim();  
  29.                 paths =paths.substring(comma + 1);  
  30.             } else {  
  31.                 path = paths.trim();  
  32.                 paths = "";  
  33.             }  
  34.    
  35.             if (path.length() < 1){  
  36.                 break;  
  37.             }  
  38.    
  39.             this.parseModuleConfigFile(digester,path);  
  40.         }  
  41.    
  42.        getServletContext().setAttribute(  
  43.             Globals.MODULE_KEY +config.getPrefix(),  
  44.             config);  
  45.    
  46.    
  47.         // Force creation and registration of DynaActionFormClass instances  
  48.         // for all dynamic form beans we wil be using  
  49.         FormBeanConfig fbs[] =config.findFormBeanConfigs();  
  50.         for (int i = 0; i < fbs.length; i++) {  
  51.             if (fbs[i].getDynamic()) {  
  52.                fbs[i].getDynaActionFormClass();  
  53.             }  
  54.         }  
  55.    
  56.         return config;  
  57. }  

       这里有必要解析一下这段代码。首先得到继承ModuleConfigFactory的实现类,如果在initModuleConfigFactory()中能设置factoryClass属性,则能生成客户化得factory,否则得到得是默认得DefaultModuleConfigFactory类,该工厂得到ModuleConfigImpl类。然后调用initConfigDigester()该方法为解析配置文件做准备,初始化Digest类(具体digest的初始化实现就不讲解)。最后返回ModuleConfig,而这时的ModuleConfig里面封装了所有的struts-config.xml中的信息。


      最后的几个方法就简单说一下就行,不是非常难理解:

      initModuleMessageResources(moduleConfig)方法是通过moduleConfig中的配置文件信息,创建MessageResource对象.

      initModuleDataSources(moduleConfig)方法是通过moduleConfig中的配置文件信息,创建DataSource对象.   initModulePlugIns(moduleConfig)加载并初始化默认应用模块的所有插件的。

      moduleConfig.freeze()是将配置文件中的各个对象,设置成已配置状态.


     最后我们看到了,下面还有一段同上面代码的循环代码,这段代码的主要意思就是当默认子应用模块被成功初始化后,如果应用还包括其他子应用模块,将重复流程,分别对其他子应用模块进行初始化。这个也是很好理解的。


     到此为止ActionServlet就init完成。

 

      经过这两篇博客的源码分析,我们能够很清晰的知道在为什么在web.xml文件下会那样配置信息,也知道程序是怎么样初始化ActionServlet的了。下一篇博客讲ActionServlet是如何截取字符串的。敬请关注

0 0
原创粉丝点击