struts2利用FilterDispatcher来拦截请求,然后进行请求的分发,在FilterDispatcher的#init()方法里,实现了配置文件的读入。
代码如下:
-------------------------------------------------------------------------------------------------
先调用#createDispatcher()来创建一个Dispatcher对象,并将FilterConfig中的属性读出,代码如下:
在#createDispatcher()中,将Filter的配置中的所有属性都写入一个HashMap并作为参数传递给Dispatcher的构造函数。
-------------------------------------------------------------------------------------------------
再回到#init()函数中,创建完Dispatcher对象后,紧接着调用Dispatcher的#init()方法。代码如下:
首先实例化一个ConfigurationManager对象。
然后就是调用一系列的#init_*()方法了。
-------------------------------------------------------------------------------------------------
●第一个是
这个方法中是将一个DefaultPropertiesProvider对象追加到ConfigurationManager对象内部的ConfigurationProvider队列中。
DefaultPropertiesProvider的#register()方法可以载入org/apache/struts2/default.properties中定义的属性。
-------------------------------------------------------------------------------------------------
●第二个是
这里负责载入的是FilterDispatcher的配置中所定义的config属性。
如果用户没有定义config属性,struts默认会载入DEFAULT_CONFIGURATION_PATHS这个值所代表的xml文件。
它的值为"struts-default.xml,struts-plugin.xml,struts.xml"。也就是说框架默认会载入这三个项目xml文件。
下一步框架会逐个判断每个config属性中定义的文件。如果文件名为"xwork.xml",框架会用XmlConfigurationProvider类去处理,反之则用StrutsXmlConfigurationProvider类去处理。
-------------------------------------------------------------------------------------------------
●第三个是
向ConfigurationManager加入了一个LegacyPropertiesConfigurationProvider。
-------------------------------------------------------------------------------------------------
●第四个是
这次处理的是FilterDispatcher的配置中所定义的actionPackages属性。传说中的Struts 2 零配置。
该参数的值是一个以英文逗号(,)隔开的字符串,每个字符串都是一个包空间,Struts 2框架将扫描这些包空间下的Action类。
-------------------------------------------------------------------------------------------------
●第五个是
此方法处理的是FilterDispatcher的配置中所定义的configProviders属性。负责载入用户自定义的ConfigurationProvider。
-------------------------------------------------------------------------------------------------
●第六个是
此方法用来处理FilterDispatcher的配置中所定义的所有属性。
-------------------------------------------------------------------------------------------------
●第七个是
-------------------------------------------------------------------------------------------------
执行完七个init_*方法后,Dispatcher的#init()会接着调用#init_PreloadConfiguration(),构建一个用于依赖注射的Container对象。
此方法首先获取到ConfigurationManager中的Configuration对象,在#getConfiguration()内部,调用上边6步添加到ConfigurationManager的ConfigurationProviders的#register()方法。
其中的重点就是DefaultConfiguration的#reload()方法。
代码如下:
public void init(FilterConfig filterConfig) throws ServletException {
this.filterConfig = filterConfig;
dispatcher = createDispatcher(filterConfig);
dispatcher.init();
String param = filterConfig.getInitParameter("packages");
String packages = "org.apache.struts2.static template org.apache.struts2.interceptor.debugging";
if (param != null) {
packages = param + " " + packages;
}
this.pathPrefixes = parse(packages);
}-------------------------------------------------------------------------------------------------
先调用#createDispatcher()来创建一个Dispatcher对象,并将FilterConfig中的属性读出,代码如下:
protected Dispatcher createDispatcher(FilterConfig filterConfig) {
Map params = new HashMap();
for (Enumeration e = filterConfig.getInitParameterNames(); e.hasMoreElements(); ) {
String name = (String) e.nextElement();
String value = filterConfig.getInitParameter(name);
params.put(name, value);
}
return new Dispatcher(filterConfig.getServletContext(), params);
}在#createDispatcher()中,将Filter的配置中的所有属性都写入一个HashMap并作为参数传递给Dispatcher的构造函数。
-------------------------------------------------------------------------------------------------
再回到#init()函数中,创建完Dispatcher对象后,紧接着调用Dispatcher的#init()方法。代码如下:
public void init() {
if (configurationManager == null) {
configurationManager = new ConfigurationManager(BeanSelectionProvider.DEFAULT_BEAN_NAME);
}
init_DefaultProperties(); // [1]
init_TraditionalXmlConfigurations(); // [2]
init_LegacyStrutsProperties(); // [3]
init_ZeroConfiguration(); // [4]
init_CustomConfigurationProviders(); // [5]
init_MethodConfigurationProvider();
init_FilterInitParameters(); // [6]
init_AliasStandardObjects(); // [7]
Container container = init_PreloadConfiguration();
init_CheckConfigurationReloading(container);
init_CheckWebLogicWorkaround(container);
}首先实例化一个ConfigurationManager对象。
然后就是调用一系列的#init_*()方法了。
-------------------------------------------------------------------------------------------------
●第一个是
private void init_DefaultProperties() {
configurationManager.addConfigurationProvider(new DefaultPropertiesProvider());
}这个方法中是将一个DefaultPropertiesProvider对象追加到ConfigurationManager对象内部的ConfigurationProvider队列中。
DefaultPropertiesProvider的#register()方法可以载入org/apache/struts2/default.properties中定义的属性。
-------------------------------------------------------------------------------------------------
●第二个是
private void init_TraditionalXmlConfigurations() {
String configPaths = initParams.get("config");
if (configPaths == null) {
configPaths = DEFAULT_CONFIGURATION_PATHS;
}
String[] files = configPaths.split("[url=file://\\s*[,]\\s]\\s*[,]\\s[/url]*");
for (String file : files) {
if (file.endsWith(".xml")) {
if ("xwork.xml".equals(file)) {
configurationManager.addConfigurationProvider(new XmlConfigurationProvider(
file, false));
} else {
configurationManager
.addConfigurationProvider(new StrutsXmlConfigurationProvider(file,
false, servletContext));
}
} else {
throw new IllegalArgumentException("Invalid configuration file name");
}
}
}这里负责载入的是FilterDispatcher的配置中所定义的config属性。
如果用户没有定义config属性,struts默认会载入DEFAULT_CONFIGURATION_PATHS这个值所代表的xml文件。
它的值为"struts-default.xml,struts-plugin.xml,struts.xml"。也就是说框架默认会载入这三个项目xml文件。
下一步框架会逐个判断每个config属性中定义的文件。如果文件名为"xwork.xml",框架会用XmlConfigurationProvider类去处理,反之则用StrutsXmlConfigurationProvider类去处理。
-------------------------------------------------------------------------------------------------
●第三个是
private void init_LegacyStrutsProperties() {
configurationManager.addConfigurationProvider(new LegacyPropertiesConfigurationProvider());
}向ConfigurationManager加入了一个LegacyPropertiesConfigurationProvider。
-------------------------------------------------------------------------------------------------
●第四个是
private void init_ZeroConfiguration() {
String packages = initParams.get("actionPackages");
if (packages != null) {
String[] names = packages.split("[url=file://\\s*[,]\\s]\\s*[,]\\s[/url]*");
// Initialize the classloader scanner with the configured packages
if (names.length > 0) {
ClasspathConfigurationProvider provider = new ClasspathConfigurationProvider(names);
provider.setPageLocator(new ServletContextPageLocator(servletContext));
configurationManager.addConfigurationProvider(provider);
}
}
}这次处理的是FilterDispatcher的配置中所定义的actionPackages属性。传说中的Struts 2 零配置。
该参数的值是一个以英文逗号(,)隔开的字符串,每个字符串都是一个包空间,Struts 2框架将扫描这些包空间下的Action类。
-------------------------------------------------------------------------------------------------
●第五个是
private void init_CustomConfigurationProviders() {
String configProvs = initParams.get("configProviders");
if (configProvs != null) {
String[] classes = configProvs.split("[url=file://\\s*[,]\\s]\\s*[,]\\s[/url]*");
for (String cname : classes) {
try {
Class cls = ClassLoaderUtils.loadClass(cname, this.getClass());
ConfigurationProvider prov = (ConfigurationProvider) cls.newInstance();
configurationManager.addConfigurationProvider(prov);
} catch (InstantiationException e) {
throw new ConfigurationException("Unable to instantiate provider: " + cname, e);
} catch (IllegalAccessException e) {
throw new ConfigurationException("Unable to access provider: " + cname, e);
} catch (ClassNotFoundException e) {
throw new ConfigurationException("Unable to locate provider class: " + cname, e);
}
}
}
}此方法处理的是FilterDispatcher的配置中所定义的configProviders属性。负责载入用户自定义的ConfigurationProvider。
-------------------------------------------------------------------------------------------------
●第六个是
private void init_FilterInitParameters() {
configurationManager.addConfigurationProvider(new ConfigurationProvider() {
public void destroy() {
}
public void init(Configuration configuration) throws ConfigurationException {
}
public void loadPackages() throws ConfigurationException {
}
public boolean needsReload() {
return false;
}
public void register(ContainerBuilder builder, LocatableProperties props)
throws ConfigurationException {
props.putAll(initParams);
}
});
}此方法用来处理FilterDispatcher的配置中所定义的所有属性。
-------------------------------------------------------------------------------------------------
●第七个是
private void init_AliasStandardObjects() {
configurationManager.addConfigurationProvider(new BeanSelectionProvider());
}-------------------------------------------------------------------------------------------------
执行完七个init_*方法后,Dispatcher的#init()会接着调用#init_PreloadConfiguration(),构建一个用于依赖注射的Container对象。
private Container init_PreloadConfiguration() {
Configuration config = configurationManager.getConfiguration();
Container container = config.getContainer();
boolean reloadi18n = Boolean.valueOf(container.getInstance(String.class,
StrutsConstants.STRUTS_I18N_RELOAD));
LocalizedTextUtil.setReloadBundles(reloadi18n);
ObjectTypeDeterminer objectTypeDeterminer = container
.getInstance(ObjectTypeDeterminer.class);
ObjectTypeDeterminerFactory.setInstance(objectTypeDeterminer);
return container;
}此方法首先获取到ConfigurationManager中的Configuration对象,在#getConfiguration()内部,调用上边6步添加到ConfigurationManager的ConfigurationProviders的#register()方法。
public synchronized Configuration getConfiguration() {
if (configuration == null) {
setConfiguration(new DefaultConfiguration(defaultFrameworkBeanName));
try {
configuration.reload(getConfigurationProviders());
} catch (ConfigurationException e) {
setConfiguration(null);
throw e;
}
} else {
conditionalReload();
}
return configuration;
}其中的重点就是DefaultConfiguration的#reload()方法。
public synchronized void reload(List providers) throws ConfigurationException {
packageContexts.clear();
loadedFileNames.clear();
ContainerProperties props = new ContainerProperties();
ContainerBuilder builder = new ContainerBuilder();
for (ConfigurationProvider configurationProvider : providers)
{
configurationProvider.init(this);
configurationProvider.register(builder, props);
}
props.setConstants(builder);
builder.factory(Configuration.class, new Factory() {
public Configuration create(Context context) throws Exception {
return DefaultConfiguration.this;
}
});
try {
// Set the object factory for the purposes of factory creation
ObjectFactory.setObjectFactory(new ObjectFactory());
container = builder.create(false);
objectFactory = container.getInstance(ObjectFactory.class);
ObjectFactory.setObjectFactory(objectFactory);
for (ConfigurationProvider configurationProvider : providers)
{
container.inject(configurationProvider);
configurationProvider.loadPackages();
}
rebuildRuntimeConfiguration();
} finally {
ObjectFactory.setObjectFactory(null);
}
}
2553

被折叠的 条评论
为什么被折叠?



