上回说到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的时候,先要初始化配置工厂,
- 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 {
-
- DefaultModuleConfigFactory的一个实例
- ModuleConfigFactory factoryObject = ModuleConfigFactory.createFactory();
- ModuleConfig config = factoryObject.createModuleConfig(prefix);
-
- Digester digester = initConfigDigester();
-
-
- 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);
-
-
-
- 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 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")异常,
现在对它的属性简单说明如下:
-
- protected HashMap actionConfigs:
-
- protected HashMap dataSources
-
- protected HashMap exceptions
-
- protected HashMap formBeans
-
- protected HashMap forwards
-
- protected HashMap messageResources
-
- protected ArrayList plugIns
-
- protected ControllerConfig controllerConfig
-
- protected boolean configured
-
- protected String prefix
-
- 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的初始化也已经完成.