项目中配置struts2在web.xml
<filter> <filter-name>struts</filter-name> <filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class> </filter>
FilterDispatcher是struts2的核心控制器,每个请求都会进入FilterDispatcher对象的doFilter()方法。然后再struts.xml文件中根据action的name属性进行匹配,找到要执行的action类和方法,执行完方法返回结果。
1、首先分析FilterDispatcher加载struts的各种配置文件。
首先看看init()方法:
public void init(FilterConfig filterConfig) throws ServletException { try { this.filterConfig = filterConfig; initLogging(); dispatcher = createDispatcher(filterConfig); dispatcher.init(); dispatcher.getContainer().inject(this); staticResourceLoader.setHostConfig(new FilterHostConfig(filterConfig)); } finally { ActionContext.setContext(null); } }
注释:(1)iniggtLoing()初始化log日志
(2)createDispatcher(filterConfig)创建dispatcher,并且通过init()初始化相应的信息
2、createDispatcher(filterConfig)方法代码:
protected Dispatcher createDispatcher(FilterConfig filterConfig) { Map<String, String> params = new HashMap<String, String>(); for (Enumeration e = filterConfig.getInitParameterNames(); e.hasMoreElements();) { String name = (String) e.nextElement(); String value = filterConfig.getInitParameter(name); params.put(name, value); } return createDispatcher(filterConfig.getServletContext(), params); }
注释:主要是把web.xml中init-param的标签数据保存到类型map的params中,然后继续调用createDispatcher(filterConfig.getServletContext(), params)创建dispatcher
3、createDispatcher(filterConfig.getServletContext(), params)的源码:
protected Dispatcher createDispatcher(ServletContext ctx, Map<String, String> params) { return new Dispatcher(ctx, params); }
注释:很简单,就是new Dispatcher对象。Dispather被称之为struts2的核心分发器,主要是基于在整个struts2框架中的特殊地位。
4、Dispatcher的构造函数:
public Dispatcher(ServletContext servletContext, Map<String, String> initParams) { this.servletContext = servletContext; this.initParams = initParams; }5、创建好d ispatcher对象,然后回到 步骤1中org.apache.struts2.dispatcher.FilterDispatcher中init()方法,然后会调用dispatcher.init(), init()方法是用来Load用户配置文件,资源文件以及默认的配置文件.
public void init() { if (configurationManager == null) { configurationManager = createConfigurationManager(BeanSelectionProvider.DEFAULT_BEAN_NAME);////设置ConfigurationManager的defaultFrameworkBeanName. //这里DEFAULT_BEAN_NAME为struts,这是xwork框架的内容,Framework可以是xwork,struts,webwork等 } try { init_DefaultProperties(); // [1]//读取properties信息,默认的default.properties init_TraditionalXmlConfigurations(); // [2]读取xml配置文件
init_LegacyStrutsProperties(); // [3]读取用户自定义的struts.properties
init_CustomConfigurationProviders(); // [5]自定义的configProviders
init_FilterInitParameters() ; // [6]载入FilterDispatcher传进来的initParams
init_AliasStandardObjects() ; // [7]将配置文件中的bean与具体的类映射 //构建一个用于依赖注射的Container对象, 在这里面会循环调用上面七个ConfigurationProvider的register方法,其中的重点就是DefaultConfiguration的#reload()方法
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); } }注释:(1)通过createConfigurationManager创建配置控制器, createConfigurationManager方法就是简单new ConfigurationManager(name)对象。
(2)init_DefaultProperties() 读取properties信息,默认的default.properties,详细分析请看步骤5.1
(3)init_TraditionalXmlConfigurations读取xml配置文件,struts-default.xml,struts-plugin.xml,struts.xml,请看步骤5.2
(4)init_LegacyStrutsProperties()读取用户自定义struts.properties
(5)init_CustomConfigurationProviders()初始化自定义的配置加载器,请看步骤5.3
(6)init_FilterInitParameters()初始化由wen.xml穿件来的运行参数 ,请看步骤5.4
(7)init_AliasStandardObjects()将配置文件中的bean与具体的类映射 ,初始化默认容器内置对象,后面会详细的解释。
到这里初始化各种形式的配置加载方法,这里只是定义了配置和加载的方法,并没有真正执行加载配置的逻辑
下面这几步初始化容器,这里包含两个不同的过程:(1)对所有定义的配置加载方式的逻辑执行,将它们初始化到configuration中(2)初始化struts2中的对象管理器
Container container = init_PreloadConfiguration();
container.inject(this);对container进行依赖注入,所有在struts2中定义的对象的生命周期在此操作后都被纳入容器管理
init_CheckConfigurationReloading(container);
init_CheckWebLogicWorkaround(container);
额外初始化,检查是否支持reloading加载和对weblogic服务器的特殊处理
5.1init_DefaultProperties() 代码:
private void init_DefaultProperties() { configurationManager.addContainerProvider(new DefaultPropertiesProvider()); }5.1.1DefaultPropertiesProvider().java代码:
public class DefaultPropertiesProvider extends LegacyPropertiesConfigurationProvider { public void destroy() { } public void init(Configuration configuration) throws ConfigurationException { } public void register(ContainerBuilder builder, LocatableProperties props) throws ConfigurationException { Settings defaultSettings = null; try { defaultSettings = new PropertiesSettings("org/apache/struts2/default"); } catch (Exception e) { throw new ConfigurationException("Could not find or error in org/apache/struts2/default.properties", e); } loadSettings(props, defaultSettings); } }注释:初始化struts2默认的properties文件,该文件是org/apache/struts2/目录下的default.properties文件
5.2init_TraditionalXmlConfigurations()加载xml配置
private static final String DEFAULT_CONFIGURATION_PATHS = "struts-default.xml,struts-plugin.xml,struts.xml"; private void init_TraditionalXmlConfigurations() { String configPaths = initParams.get("config"); if (configPaths == null) { configPaths = DEFAULT_CONFIGURATION_PATHS; } String[] files = configPaths.split("\\s*[,]\\s*"); for (String file : files) { if (file.endsWith(".xml")) { if ("xwork.xml".equals(file)) { configurationManager.addContainerProvider(createXmlConfigurationProvider(file, false)); } else { configurationManager.addContainerProvider(createStrutsXmlConfigurationProvider(file, false, servletContext)); } } else { throw new IllegalArgumentException("Invalid configuration file name"); } } }
protected XmlConfigurationProvider createStrutsXmlConfigurationProvider(String filename, boolean errorIfMissing, ServletContext ctx) { return new StrutsXmlConfigurationProvider(filename, errorIfMissing, ctx); }5.3init_CustomConfigurationProviders()--初始化用户自定义的配置加载器,代码:
private void init_CustomConfigurationProviders() { String configProvs = initParams.get("configProviders"); if (configProvs != null) { String[] classes = configProvs.split("\\s*[,]\\s*"); for (String cname : classes) { try { Class cls = ClassLoaderUtils.loadClass(cname, this.getClass()); ConfigurationProvider prov = (ConfigurationProvider)cls.newInstance(); configurationManager.addContainerProvider(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); } } } }5.4init_FilterInitParameters()--初始化由web.xml传入的运行参数,代码:
private void init_FilterInitParameters() { configurationManager.addContainerProvider(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); } }); }