上回說到Struts的ActionServlet,其中有一步是 initModuleConfig方法,就是用於初始化MoudleConfig執行個體,它是整個org.apache.struts.config包的核心,在Struts應用運行時用來存放整個Struts應用的配置資訊.如果有多個子應用,每個子應用都會有一個ModuleConfig對象.ModuleConfig和Struts設定檔的根項目<struts-config>對應.<struts-config>根項目中包含<form-bean>,<action>和<forward>等一系列子項目,因此MouduleConfig中包含了和每個子項目對應的配置類執行個體.
同時Struts中的MessageResource、PlugIn、資料來源等,都是通過ModuleConfig來實現的,所以在ActionServlet初始化上面的那些模組之前,就先要初始化ModuleConfig,然後由ModuleConfig來負責其初始化。
struts中讀模數塊配置MoudleConfig採用了這樣的Factory 方法
一個介面:ModuleConfig.java
一個抽象類別:ModuleConfigFactory.java
一個ModuleConfig的實作類別:ModuleConfigImpl.java
一個ModuleConfigFactory的子類:DefaultModuleConfigFactory.java
具體介紹
一.initModuleConfigFactory()
在ActionServlet初始化ModuleConfig的時候,先要初始化配置工廠,
代碼 initModuleConfigFactory();
那麼這個工廠到底初始化了什麼。
現看原始碼:
代碼 protected void initModuleConfigFactory(){ String configFactory = getServletConfig().getInitParameter("configFactory"); if (configFactory != null) { ModuleConfigFactory.setFactoryClass(configFactory); } }
很明顯,現從配置參數取得其配置,如果使用者沒有作配置,那麼就使用預設配置,如果使用者作了配置,那麼就使用使用者的配置。
如果使用者作了配置的話,那麼就執行設定成使用者的工廠。如何設定的呢。
代碼 public static void setFactoryClass(String factoryClass) { ModuleConfigFactory.factoryClass = factoryClass; ModuleConfigFactory.clazz = null; }
直接給ModuleConfigFactory.factoryClass賦值,因為此變數是一個靜態變數:
代碼 protected static String factoryClass = "org.apache.struts.config.impl.DefaultModuleConfigFactory";
由此定義決定了可以使用此賦值方法。正是因為此變數是一個靜態變數,所以在下面的得工廠產生對象的時候就可以建立一個使用者自己的對象。
二.initModuleConfig()
之後由配置工廠再執行個體化一個ModuleConfig的對象。
代碼 ModuleConfig moduleConfig = initModuleConfig("", config);
看一下initModuleConfig方法是如何初始化ModuleConfig的,看下面的原始碼:
代碼 protected ModuleConfig initModuleConfig(String prefix, String paths) throws ServletException { //這個地方,我們可以看到,此時就由ModuleConfigFactory直接建立了一個工廠對象,而此時我們用的配置就是上面我們初始化後的配置。如果使用者自己做了配置,那麼此時初始化的工廠就是使用者指定後的工廠。如果沒有的話,那麼就初始化的時預設的工廠。 DefaultModuleConfigFactory的一個執行個體 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; }
三.createModuleConfig()方法
那麼初始化配置模組createModuleConfig方法到底做了什麼呢。
其實是產生了一個ModuleConfig的對象。這個對象是由其工廠產生的,由什麼樣的工廠就會產生什麼樣的產品。所以如果是使用者配置過的工廠,那麼就會產生其對應的配置模組的實現。
預設的情況:
代碼 public class DefaultModuleConfigFactory extends ModuleConfigFactory implements Serializable{ // --------------------------------------------------------- Public Methods /** * Create and return a newly instansiated {@link ModuleConfig}. * This method must be implemented by concrete subclasses. * * @param prefix Module prefix for Configuration */ public ModuleConfig createModuleConfig(String prefix) { return new ModuleConfigImpl(prefix); } }
它的createModuleConfig(String prefix)方法會產生一個ModuleConfigImpl類。
四.ModuleConfigImpl類
ModuleConfigImpl類相當於一個JavaBean,用來存放一個web模組運行時所需要的配置資訊。當 然,一個web模組可以擁有多個ModuleConfig,但是預設的是prefix長度為0的ModuleConifg。它 的每個屬性幾乎都是由HashMap組成的,它通過一個configured布爾值來描述當前的ModuleConfig是否已經被初始化完畢,在每存放一個屬性的時候都會監測這個值。如果初始化完畢而還要改變裡面的屬性值,則會報出IllegalStateException("Configuration is frozen")異常,
現在對它的屬性簡單說明如下:
代碼 // 這個HashMap用來儲存ActionConfig對象。 protected HashMap actionConfigs: //HashMap用來儲存DataSourceConfig對象。 protected HashMap dataSources //這個HashMap用來儲存ExceptionConfig對象。 protected HashMap exceptions //這個HashMap用來儲存FormBeanConfig對象。 protected HashMap formBeans //這個HashMap用來儲存ForwardConfig對象。 protected HashMap forwards //這個HashMap用來儲存MessageResourcesConfig對象。 protected HashMap messageResources //這個HashMap用來儲存PlugInConfig對象。 protected ArrayList plugIns //ControllerConfig類 protected ControllerConfig controllerConfig //標誌這個ModuleConfig是(true)否(false)配置完成。 protected boolean configured //用來標誌和區分ModuleConfig類,同時在使用上面的config類初始化相應的資源以後,也是通過這個prefix來區分所屬的不同的web模組。 protected String prefix //ActionMapping類名,預設為org.apache.struts.action.ActionMapping。[ protected String actionMappingClass = "org.apache.struts.action.ActionMapping"
ModuleConfigImpl類的ModuleConfigImpl方法如下
代碼 public ModuleConfigImpl(String prefix) { super(); this.prefix = prefix; this.actionConfigs = new HashMap(); this.actionConfigList = new ArrayList(); this.actionFormBeanClass = "org.apache.struts.action.ActionFormBean"; this.actionMappingClass = "org.apache.struts.action.ActionMapping"; this.actionForwardClass = "org.apache.struts.action.ActionForward"; this.configured = false; this.controllerConfig = null; this.dataSources = new HashMap(); this.exceptions = new HashMap(); this.formBeans = new HashMap(); this.forwards = new HashMap(); this.messageResources = new HashMap(); this.plugIns = new ArrayList(); }
通過其預設工廠的實現,我們可以看到,其執行個體化了一個ModuleConfigImpl的對象,這是ModuleConfig的一種實現,也是當前struts的預設的實現。
這是初始化過程開始逐漸明朗.
調用過程factoryObject.createModuleConfig(prefix)--->DefaultModuleConfigFactory 的createModuleConfig(prefix)---->new ModuleConfigImpl(prefix),但好像還有一個問題,ModuleConfigImpl類的ModuleConfigImpl方法裡對其屬性都是new的,沒賦值啊?後來仔細看了半天,發現在initModuleConfig方法裡還有幾行代碼
代碼 ....... Digester digester = initConfigDigester(); ....... igester.push(config); ....... this.parseModuleConfigFile(digester, path); .....
應該是digster攜帶config執行個體在parseModuleConfigFile方法裡初始化好了.
五.UserModuleConfigFactory
如果是使用者配置了實現工廠的話,可能的實現就是:
代碼 public class UserModuleConfigFactory extends ModuleConfigFactory implements Serializable{ public ModuleConfig createModuleConfig(String prefix) { return new ModuleConfigUserImpl(prefix); } }
當然,如果要啟用你的工廠的話,那麼還要在你的設定檔中添加如下部分,在web.xml中修改如下部分:
代碼 <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>3</param-value> </init-param> <init-param> <param-name>detail</param-name> <param-value>3</param-value> </init-param> <init-param> <param-name>configFactory</param-name> <param-value>org.aa.struts. UserModuleConfigFactory </param-value> </init-param> <load-on-startup>0</load-on-startup> </servlet>
這樣的話,你的工廠就可以生效了,也可以產生你自己的配置模組的執行個體了。
到此,配置模組MoudelConfig的初始化也已經完成.