1、StrutsPrepareAndExecuteFilter实现了Filter接口 init方法为初始化入口 StrutsPrepareAndExecuteFilter init方法 1. public void init(FilterConfig filterConfig) throws ServletException { 2. //初始化辅助类 类似一个Delegate 3. InitOperations init = new InitOperations(); 4. try { 5. // FilterHost
2、Config 封装了FilterConfig参数对象 6. FilterHostConfig config = new FilterHostConfig(filterConfig); 7. //LoggerFactory配置加载 8. //如果没有web.xml 没有配置“loggerFactory”参数 尝试mons.logging.LogFactory 9. //如果失败 使用JdkLoggerFactory 10. //TODO SPI 11. ini
3、t.initLogging(config); 12. //TODO 创建Dispatcher 注册加载器 执行加载器 创建容器 解析xml 13. Dispatcher dispatcher = init.initDispatcher(config); 14. init.initStaticContentLoader(config, dispatcher); 15. //预处理类 请求处理时才会真正用到 16. //1.主要负责在每次请求 创建ActionConte
4、xt 清除ActionContext 17. //2.当接收到一个请求时 通过uri查找 ActionConfig 创建ActionMapping 18. prepare = new PrepareOperations(filterConfig.getServletContext(), dispatcher); //处理请求 Delegate 19. execute = new ExecuteOperations(filterConfig.getServletContext(), dispatcher
5、); this.excludedPatterns = init.buildExcludedPatternsList(dispatcher); 20. //空实现 留作扩展 21. postInit(dispatcher, filterConfig); 22. } finally { 23. init.cleanup(); 24. } 25. } InitOperations 类似与一个Delegate 主要负责实例化Dispatche 再把初始化操作转
6、交给Dispatche init处理 1. public Dispatcher initDispatcher( HostConfig filterConfig ) { 2. //创建Dispatcher 3. Dispatcher dispatcher = createDispatcher(filterConfig); 4. //核心方法 Container容器的创建 xml解析在此方法发生 5. dispatcher.init(); 6. return dispatcher; 7. } 8. 9
7、 private Dispatcher createDispatcher( HostConfig filterConfig ) {
10. Map
8、 filterConfig.getInitParameter(name); 14. params.put(name, value); 15. } 16. return new Dispatcher(filterConfig.getServletContext(), params); 17. } Dispatcher init方法 1.针对配置文件 注册不同的加载器 保存到ConfigurationManager类中的一个变量中 2.创建容器 解析xml 1. public void init() { 2. //创
9、建配置操作管理类 , 会保存元素加载器 3. if (configurationManager == null) { 4. configurationManager = createConfigurationManager(BeanSelectionProvider.DEFAULT_BEAN_NAME); 5. } 6. try { 7. /**初始化各种形式加载器,保存到ConfigurationManager#containerProviders Map集合中 8. 没有真
10、正执行加载 解析逻辑*/ 9. //org/apache/struts2/default.properties属性文件 里面定义了一系列struts常量 10. init_DefaultProperties(); // [1] 11. //web.xml配置的 config参数 [配置多个用","分开] 12. //如果没有该参数 默认为 struts-default.xml[框架级],struts-plugin.xml[框架级],struts.xml[系统级别] 13. //根据文件名称 创
11、建加载器 加载xml主要有一下两个解析器 14. //XmlConfigurationProvider[xwork.xml], 15. //StrutsXmlConfigurationProvider[struts相关配置文件]配置元素加载器 16. init_TraditionalXmlConfigurations(); // [2] 17. //struts.locale 注册 18. init_LegacyStrutsProperties();
12、// [3] 19. //实例化 我们自定义的加载器 保存到containerProviders集合中 20. // web.xml configProviders参数 多个用","分开 21. //配置器必须是ConfigurationProvider接口的实例 22. //TODO SPI 23. init_CustomConfigurationProviders(); // [5] 24. //web.xm
13、l配置的init-param参数 加载器 最终会保存到Container容器中 25. init_FilterInitParameters() ; // [6] 26. //TODO 根据我们在struts.xml定义的 常量 选择插件类 27. //比如集成spring 会用到org.apache.struts2.spring.StrutsSpringObjectFactory 28. init_AliasStandardObjects() ; // [7] 29
14、 /** 执行加载器 */ 30. //TODO 创建容器 解析xml 真正执行加载器方法 31. Container container = init_PreloadConfiguration(); 32. //执行当前Dispatcher对象 依赖关系注入 33. container.inject(this); 34. //额外动作 35. init_CheckConfigurationR
15、eloading(container); 36. init_CheckWebLogicWorkaround(container); 37. } catch (Exception ex) { 38. if (LOG.isErrorEnabled()) 39. LOG.error("Dispatcher initialization failed", ex); 40. throw new StrutsException(ex); 41.
16、 } 42. } ConfigurationManager 主要管理 创建的各种加载器 1. public class ConfigurationManager { 2. protected static final Logger LOG = LoggerFactory.getLogger(ConfigurationManager.class); 3. //配置元素管理器 4. protected Configuration configuration; 5. protected Lock providerLo
17、ck = new ReentrantLock();
6. //创建的xml加载器会保存到次集合中
7. private List
18、ame - > struts 3. return new ConfigurationManager(name); 4. } 1.default.properties 属性文件加载器 1. private void init_DefaultProperties() { 2. //保存到ConfigurationManager加载器集合中 3. configurationManager.addConfigurationProvider(new DefaultPropertiesProvider()); 4. } 2.创建stru
19、ts相关文件加载器 StrutsXmlConfigurationProvider 1. private void init_TraditionalXmlConfigurations() { 2. //web.xml 配置的config 3. String configPaths = initParams.get("config"); 4. if (configPaths == null) { 5. //如果没有配置 默认 struts-default.xml,struts-plugin.xml,struts.xml 6
20、 configPaths = DEFAULT_CONFIGURATION_PATHS; 7. } 8. String[] files = configPaths.split("\\s*[,]\\s*"); 9. for (String file : files) { 10. if (file.endsWith(".xml")) { 11. if ("xwork.xml".equals(file)) { 12. configurationManager.addCo
21、nfigurationProvider(createXmlConfigurationProvider(file, false)); 13. } else { 14. //struts xml加载器 15. //StrutsXmlConfigurationProvider 16. configurationManager.addConfigurationProvider(createStrutsXmlConfigurationProvider(fil
22、e, false, servletContext)); 17. } 18. } else { 19. throw new IllegalArgumentException("Invalid configuration file name"); 20. } 21. } 22. } 23. protected XmlConfigurationProvider createXmlConfigurationProvider(String filename, boolean
23、errorIfMissing) { 24. return new XmlConfigurationProvider(filename, errorIfMissing); 25. } 26. protected XmlConfigurationProvider createStrutsXmlConfigurationProvider(String filename, boolean errorIfMissing, ServletContext ctx) { 27. return new StrutsXmlConfigurationProvider(file
24、name, errorIfMissing, ctx); 28. } 3.web.xml扩展的ContainerProviders加载器 实例化 1. private void init_CustomConfigurationProviders() { 2. //web.xml 中configProviders 节点 3. String configProvs = initParams.get("configProviders"); 4. if (configProvs != null) { 5. String[] c
25、lasses = configProvs.split("\\s*[,]\\s*"); 6. for (String cname : classes) { 7. Class cls = ClassLoaderUtils.loadClass(cname, this.getClass()); 8. ConfigurationProvider prov = (ConfigurationProvider)cls.newInstance(); 9. configurationManager.addConfigur
26、ationProvider(prov); 10. } 11. } 12. } init_PreloadConfiguration 方法主要完成创建容器, 解析xml动作 1. private Container init_PreloadConfiguration() { 2. //创建Container 解析xml 3. Configuration config = configurationManager.getConfiguration(); 4. Container container
27、 config.getContainer(); 5. boolean reloadi18n = Boolean.valueOf(container.getInstance(String.class, StrutsConstants.STRUTS_I18N_RELOAD)); 6. LocalizedTextUtil.setReloadBundles(reloadi18n); 7. return container; 8. } init_PreloadConfiguration 方法中调用了 ConfigurationManager的
28、getConfiguration 方法 1. public synchronized Configuration getConfiguration() { 2. //创建配置元素管理器 3. if (configuration == null) { 4. // defaultFrameworkBeanName - > struts 5. setConfiguration(createConfiguration(defaultFrameworkBeanName)); 6. try { 7.
29、 // getContainerProviders 返回注册的各种加载器 8. // reloadContainer 创建Container 解析xml 9. configuration.reloadContainer(getContainerProviders()); 10. } catch (ConfigurationException e) { 11. setConfiguration(null); 12. throw
30、new ConfigurationException("Unable to load configuration.", e); 13. } 14. } else { 15. conditionalReload(); 16. } 17. return configuration; 18. } [java] view plaincopyprint? 1. protected Configuration createConfiguration(String beanName) { 2.
31、 return new DefaultConfiguration(beanName);
3. }
DefaultConfiguration的reloadContainer方法 会去执行已注册的各种加载器 ,和创建容器
1. public synchronized List
32、 loadedFileNames.clear();
4. List
33、 9. for (final ContainerProvider containerProvider : providers) { 10. /** 11. * 初始化Document 准备解析 12. * 具体在XmlConfigurationProvider实现类 会处理include节点 13. * 处理完成之后Document会保存到XmlConfigurationProvider#documents list集合中 14.
34、 * include file路径会保存到XmlConfigurationProvider#loadedFileUrls set集合中 15. * 从代码中发现 include file属性中 可以使用通配符 "*" 16. */ 17. /** StrutsXmlConfigurationProvider 是 XmlConfigurationProvider的子类 */ 18. /** StrutsXmlConfigurationProvider struts*.x
35、ml */ 19. containerProvider.init(this); 20. //针对"bean","constant","unknown-handler-stack"节点 不包括"package"节点 解析xml 21. //每一个bean 对应一个LocatableFactory LocatableFactory保存了bean的定义 22. //bean定义 保存到ContainerBuilder#factories map集合中 23.
36、 //配置文件中定义的常量 保存到props中 24. containerProvider.register(builder, props); 25. } 26. //将常量保存到ContainerBuilder#factories map集合中 27. //每一个常量对应一个LocatableConstantFactory 28. props.setConstants(builder); 29. builder.factory(Configu
37、ration.class, new Factory
38、 try { 36. //创建辅助容器 ContainerImpl并且 实例化 struts一些核心类 37. Container bootstrap = createBootstrapContainer(); 38. setContext(bootstrap); 39. //主容器 这是一个全局变量 40. container = builder.create(false); 41. setC
39、ontext(container); 42. objectFactory = container.getInstance(ObjectFactory.class); 43. // Process the configuration providers first 44. for (final ContainerProvider containerProvider : providers) { 45. if (containerProvider instanceof P
40、ackageProvider) { 46. //com.opensymphony.xwork2.config.providers.XmlConfigurationProvider#setObjectFactory(ObjectFactory) 47. container.inject(containerProvider); 48. //解析 xml package节点 49. //保存packageConte
41、xts map集合中 50. //com.opensymphony.xwork2.config.providers.XmlConfigurationProvider line 481 ((PackageProvider) containerProvider).loadPackages(); 51. packageProviders.add((PackageProvider) containerProvider); 52. } 53
42、 }
54. // Then process any package providers from the plugins
55. Set
43、s) { 57. PackageProvider provider = container.getInstance(PackageProvider.class, name); 58. provider.init(this); 59. provider.loadPackages(); 60. packageProviders.add(provider); 61. } 62.
44、 } 63. //TODO 64. rebuildRuntimeConfiguration(); 65. } finally { 66. if (oldContext == null) { 67. ActionContext.setContext(null); 68. } 69. } 70. return packageProviders; 71. }
45、 StrutsXmlConfigurationProvider的init方法 具体在父类XmlConfigurationProvider中实现 1. public void init(Configuration configuration) { 2. this.configuration = configuration; 3. this.includedFileNames = configuration.getLoadedFileNames(); 4. // configFileName ->struts.xml 5. //1.递
46、归处理include节点
6. //2.生成Document 集合
7. loadDocuments(configFileName);
8. }
loadDocuments方法中调用了loadConfigurationFiles方法 返回一个Document集合
1. private void loadDocuments(String configFileName) {
2. loadedFileUrls.clear();
3. //List
47、 = loadConfigurationFiles(configFileName, null);
5. }
loadConfigurationFiles方法 递归处理include节点 最终生成Document集合
1. private List
48、inalDocs = new ArrayList
49、dedFileNames.add(fileName);
10. Iterator






