本文只是自己看源码的一些记录。
要使用struts2 首先要在web.xml里面配置struts2的过滤器。
<filter>
<filter-name>struts2</filter-name>
<filter-class>
org.apache.struts2.dispatcher.FilterDispatcher
</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>*.do</url-pattern>
</filter-mapping>
(不过在新版本里面已经不推荐配置FilterDispatcher,而是StrutsPrepareFilter和StrutsExecuteFilter,不过我还是看的FilterDispathcher,原理我想应该是差不多的。)
FilterDispatcher实现了Filter接口。
a.init()方法 。 下面是源码
public void init(FilterConfig filterConfig) throws ServletException {
try {
this.filterConfig = filterConfig;
initLogging();
dispatcher = createDispatcher(filterConfig); //1.创建dispatcher 对象。
dispatcher.init();
dispatcher.getContainer().inject(this);
staticResourceLoader.setHostConfig(new FilterHostConfig(filterConfig));
} finally {
ActionContext.setContext(null);
}
}
1. dispatcher 是struts2 最重要的对象,我理解为struts2的分派器。这个方法可以理解为将ServletContext 全部交给dispatcher管理。
dispatcher对象包含一个私有的属性:private ServletContext servletContext; 下面是Dispatcher的构造方法。
public Dispatcher(ServletContext servletContext, Map<String, String> initParams) {
this.servletContext = servletContext;
this.initParams = initParams;
}
2. dispatcher.init(); 完成dispatcher的初始化。
public void init() {
if (configurationManager == null) {
configurationManager = createConfigurationManager(BeanSelectionProvider.DEFAULT_BEAN_NAME);
}
try {
init_DefaultProperties(); // [1]
init_TraditionalXmlConfigurations(); // [2]
init_LegacyStrutsProperties(); // [3]
init_CustomConfigurationProviders(); // [5]
init_FilterInitParameters() ; // [6]
init_AliasStandardObjects() ; // [7]
Container container = init_PreloadConfiguration();
container.inject(this);
init_CheckConfigurationReloading(container);
init_CheckWebLogicWorkaround(container);
if (!dispatcherListeners.isEmpty()) {
for (DispatcherListener l : dispatcherListeners) {
l.dispatcherInitialized(this);
}
}
} catch (Exception ex) {
if (LOG.isErrorEnabled())
LOG.error("Dispatcher initialization failed", ex);
throw new StrutsException(ex);
}
}
--------------------------------------------------------------------------------------------------------------
a.) configurationManager = createConfigurationManager(BeanSelectionProvider.DEFAULT_BEAN_NAME);
构造一个配置管理器configurationManager ,并将属性 defaultFrameworkBeanName 设置为“struts”;
b.) init_DefaultProperties(); // [1]
private void init_DefaultProperties() {
configurationManager.addConfigurationProvider(new DefaultPropertiesProvider());
}
初始化一个DefaultPropertiesProvider对象,并将它加入configurationManager对象中的containerProviders队列中。
DefaultPropertiesProvider 我理解为 默认配置文件提供者,指的是 default.properties
c.) init_TraditionalXmlConfigurations();
初始化 StrutsXmlConfigurationProvider对象,并将它加入configurationManager对象中的containerProviders队列中。这里会分别针对
struts-default.xml , struts-plugin.xml , struts.xml 构造3个对象。
d.) init_LegacyStrutsProperties();
将LegacyPropertiesConfigurationProvider 对象加入containerProviders队列中。主要是针对本地的配置文件 struts.properties
e.)init_CustomConfigurationProviders();
我们一般不会在configFilter 配置configProviders参数。所以这里暂时忽略掉了。
f.)init_FilterInitParameters().
针对ConfigFilter 的initParams。
g.) init_AliasStandardObjects()
BeanSelectionProvider 对象加入containerProviders队列中
f.)
Container container = init_PreloadConfiguration();
struts2 容器的产生就是在这个方法里面。
我们进入这个方法后,有一段这样的代码。 Configuration config = configurationManager.getConfiguration();
再次进入getConfiguration()方法中,可以看到代码
public synchronized Configuration getConfiguration() {
if (configuration == null) {
setConfiguration(createConfiguration(defaultFrameworkBeanName));
try {
//重点就是在这里, 这就是处理所有我们刚才containerProviders队列 中加入的所有对象
configuration.reloadContainer(getContainerProviders());
} catch (ConfigurationException e) {
setConfiguration(null);
throw new ConfigurationException("Unable to load configuration.", e);
}
} else {
conditionalReload();
}
return configuration;
}
我们再进入 reloadContainer 方法。
public synchronized List<PackageProvider> reloadContainer(List<ContainerProvider> providers) throws ConfigurationException {
packageContexts.clear();
loadedFileNames.clear();
List<PackageProvider> packageProviders = new ArrayList<PackageProvider>();
ContainerProperties props = new ContainerProperties();
ContainerBuilder builder = new ContainerBuilder();
for (final ContainerProvider containerProvider : providers)
{
// 循环读入配置文件 例如struts.xml
containerProvider.init(this);
//循环调用 之前的containerProviders队列中 对象的register方法
containerProvider.register(builder, props);
}
props.setConstants(builder);
builder.factory(Configuration.class, new Factory<Configuration>() {
public Configuration create(Context context) throws Exception {
return DefaultConfiguration.this;
}
});
ActionContext oldContext = ActionContext.getContext();
try {
// Set the bootstrap container for the purposes of factory creation
Container bootstrap = createBootstrapContainer();
setContext(bootstrap);
container = builder.create(false);
setContext(container);
objectFactory = container.getInstance(ObjectFactory.class);
// Process the configuration providers first
for (final ContainerProvider containerProvider : providers)
{
if (containerProvider instanceof PackageProvider) {
container.inject(containerProvider);
((PackageProvider)containerProvider).loadPackages();
packageProviders.add((PackageProvider)containerProvider);
}
}
// Then process any package providers from the plugins
Set<String> packageProviderNames = container.getInstanceNames(PackageProvider.class);
if (packageProviderNames != null) {
for (String name : packageProviderNames) {
PackageProvider provider = container.getInstance(PackageProvider.class, name);
provider.init(this);
provider.loadPackages();
packageProviders.add(provider);
}
}
rebuildRuntimeConfiguration();
} finally {
if (oldContext == null) {
ActionContext.setContext(null);
}
}
return packageProviders;
}