上回說到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采用了這樣的工廠方法
一個接口:ModuleConfig.java
一個抽象類:ModuleConfigFactory.java
一個ModuleConfig的實現類:ModuleConfigImpl.java
一個ModuleConfigFactory的子類:DefaultModuleConfigFactory.java
具體介紹
一.initModuleConfigFactory()
在ActionServlet初始化ModuleConfig的時候,先要初始化配置工廠,
那么這個工廠到底初始化了什么?
現看源代碼:
很明顯,現從配置參數取得其配置,如果用戶沒有作配置,那么就使用默認配置,如果用戶作了配置,那么就使用用戶的配置。
如果用戶作了配置的話,那么就執行設置成用戶的工廠。如何設置的呢?
直接給ModuleConfigFactory.factoryClass賦值,因為此變量是一個靜態的變量:
???
由此定義決定了可以使用此賦值方法。正是因為此變量是一個靜態的變量,所以在下面的得工廠生成對象的時候就可以創建一個用戶自己的對象。
二.initModuleConfig()
之后由配置工廠再實例化一個ModuleConfig的對象。
看一下initModuleConfig方法是如何初始化ModuleConfig的,看下面的源代碼:
三.createModuleConfig()方法
那么初始化配置模塊createModuleConfig方法到底做了什么呢?
其實是生成了一個ModuleConfig的對象。這個對象是由其工廠產生的,由什么樣的工廠就會生成什么樣的產品。所以如果是用戶配置過的工廠,那么就會生成其對應的配置模塊的實現。
默認的情況:
它的createModuleConfig(String prefix)方法會生成一個ModuleConfigImpl類。
四.ModuleConfigImpl類
??? ModuleConfigImpl類相當于一個JavaBean,用來存放一個web模塊運行時所需要的配置信息。當 然,一個web模塊可以擁有多個ModuleConfig,但是缺省的是prefix長度為0的ModuleConifg。它 的每個屬性幾乎都是由HashMap組成的,它通過一個configured布爾值來描述當前的ModuleConfig是否已經被初始化完畢,在每存放一個屬性的時候都會監測這個值。如果初始化完畢而還要改變里面的屬性值,則會報出IllegalStateException("Configuration is frozen")異常,
現在對它的屬性簡單說明如下:
?????
ModuleConfigImpl類的ModuleConfigImpl方法如下
通過其默認工廠的實現,我們可以看到,其實例化了一個ModuleConfigImpl的對象,這是ModuleConfig的一種實現,也是當前struts的默認的實現。
這是初始化過程開始逐漸明朗.
調用過程factoryObject.createModuleConfig(prefix)--->DefaultModuleConfigFactory 的createModuleConfig(prefix)---->new ModuleConfigImpl(prefix), 但好像還有一個問題,ModuleConfigImpl類的ModuleConfigImpl方法里對其屬性都是new的,沒賦值啊?后來仔細看了半天,發現在initModuleConfig方法里還有幾行代碼
應該是digster攜帶config實例在parseModuleConfigFile方法里初始化好了.
五.UserModuleConfigFactory
如果是用戶配置了實現工廠的話,可能的實現就是:
??? 當然,如果要啟用你的工廠的話,那么還要在你的配置文件中添加如下部分,在web.xml中修改如下部分:
這樣的話,你的工廠就可以生效了,也可以生成你自己的配置模塊的實例了。
到此,配置模塊MoudelConfig的初始化也已經完成.
同時Struts中的MessageResource、PlugIn、數據源等,都是通過ModuleConfig來實現的,所以在ActionServlet初始化上面的那些模塊之前,就先要初始化ModuleConfig,然后由ModuleConfig來負責其初始化。
struts中讀取模塊配置MoudleConfig采用了這樣的工廠方法
一個接口:ModuleConfig.java
一個抽象類:ModuleConfigFactory.java
一個ModuleConfig的實現類:ModuleConfigImpl.java
一個ModuleConfigFactory的子類:DefaultModuleConfigFactory.java
具體介紹
一.initModuleConfigFactory()
在ActionServlet初始化ModuleConfig的時候,先要初始化配置工廠,
- initModuleConfigFactory();??
initModuleConfigFactory();
那么這個工廠到底初始化了什么?
現看源代碼:
- protected ? void ?initModuleConfigFactory(){ ??
- ????????String?configFactory?=?getServletConfig().getInitParameter( "configFactory" ); ??
- ???????? if ?(configFactory?!=? null )?{ ??
- ????????????ModuleConfigFactory.setFactoryClass(configFactory); ??
- ????????} ??
- }??
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 ; ??
- }??
public static void setFactoryClass(String factoryClass) { ModuleConfigFactory.factoryClass = factoryClass; ModuleConfigFactory.clazz = null; }
直接給ModuleConfigFactory.factoryClass賦值,因為此變量是一個靜態的變量:
???
- protected ? static ?String?factoryClass?= ??
- ???????? "org.apache.struts.config.impl.DefaultModuleConfigFactory" ;??
protected static String factoryClass = "org.apache.struts.config.impl.DefaultModuleConfigFactory";
由此定義決定了可以使用此賦值方法。正是因為此變量是一個靜態的變量,所以在下面的得工廠生成對象的時候就可以創建一個用戶自己的對象。
二.initModuleConfig()
之后由配置工廠再實例化一個ModuleConfig的對象。
- ModuleConfig?moduleConfig?=?initModuleConfig( "" ,?config);??
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; ??
- ?}??
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); ??
- ??
- ????} ??
- }??
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" ??
// 這個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(); ??
- ??}??
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); ??
- .....??
....... Digester digester = initConfigDigester(); ....... digester.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); ??
- ????} ??
- }??
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>??
<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的初始化也已經完成.
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
