资源描述
StrutsPrepareAndExecuteFilter实现了Filter接口 init方法为初始化入口
StrutsPrepareAndExecuteFilter init方法
1. public void init(FilterConfig filterConfig) throws ServletException {
2. //初始化辅助类 类似一个Delegate
3. InitOperations init = new InitOperations();
4. try {
5. // FilterHostConfig 封装了FilterConfig参数对象
6. FilterHostConfig config = new FilterHostConfig(filterConfig);
7. //LoggerFactory配置加载
8. //如果没有web.xml 没有配置“loggerFactory”参数 尝试mons.logging.LogFactory
9. //如果失败 使用JdkLoggerFactory
10. //TODO SPI
11. init.initLogging(config);
12. //TODO 创建Dispatcher 注册加载器 执行加载器 创建容器 解析xml
13. Dispatcher dispatcher = init.initDispatcher(config);
14. init.initStaticContentLoader(config, dispatcher);
15. //预处理类 请求处理时才会真正用到
16. //1.主要负责在每次请求 创建ActionContext 清除ActionContext
17. //2.当接收到一个请求时 通过uri查找 ActionConfig 创建ActionMapping
18. prepare = new PrepareOperations(filterConfig.getServletContext(), dispatcher); //处理请求 Delegate
19. execute = new ExecuteOperations(filterConfig.getServletContext(), dispatcher); this.excludedPatterns = init.buildExcludedPatternsList(dispatcher);
20. //空实现 留作扩展
21. postInit(dispatcher, filterConfig);
22. } finally {
23. init.cleanup();
24. }
25. }
InitOperations 类似与一个Delegate 主要负责实例化Dispatche 再把初始化操作转交给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. private Dispatcher createDispatcher( HostConfig filterConfig ) {
10. Map<String, String> params = new HashMap<String, String>();
11. for ( Iterator e = filterConfig.getInitParameterNames(); e.hasNext(); ) {
12. String name = (String) e.next();
13. String value = 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. //创建配置操作管理类 , 会保存元素加载器
3. if (configurationManager == null) {
4. configurationManager = createConfigurationManager(BeanSelectionProvider.DEFAULT_BEAN_NAME);
5. }
6. try {
7. /**初始化各种形式加载器,保存到ConfigurationManager#containerProviders Map集合中
8. 没有真正执行加载 解析逻辑*/
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. //根据文件名称 创建加载器 加载xml主要有一下两个解析器
14. //XmlConfigurationProvider[xwork.xml],
15. //StrutsXmlConfigurationProvider[struts相关配置文件]配置元素加载器
16. init_TraditionalXmlConfigurations(); // [2]
17. //struts.locale 注册
18. init_LegacyStrutsProperties(); // [3]
19. //实例化 我们自定义的加载器 保存到containerProviders集合中
20. // web.xml configProviders参数 多个用","分开
21. //配置器必须是ConfigurationProvider接口的实例
22. //TODO SPI
23. init_CustomConfigurationProviders(); // [5]
24. //web.xml配置的init-param参数 加载器 最终会保存到Container容器中
25. init_FilterInitParameters() ; // [6]
26. //TODO 根据我们在struts.xml定义的 常量 选择插件类
27. //比如集成spring 会用到org.apache.struts2.spring.StrutsSpringObjectFactory
28. init_AliasStandardObjects() ; // [7]
29. /** 执行加载器 */
30. //TODO 创建容器 解析xml 真正执行加载器方法
31. Container container = init_PreloadConfiguration();
32. //执行当前Dispatcher对象 依赖关系注入
33. container.inject(this);
34. //额外动作
35. init_CheckConfigurationReloading(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. }
42. }
ConfigurationManager 主要管理 创建的各种加载器
1. public class ConfigurationManager {
2. protected static final Logger LOG = LoggerFactory.getLogger(ConfigurationManager.class);
3. //配置元素管理器
4. protected Configuration configuration;
5. protected Lock providerLock = new ReentrantLock();
6. //创建的xml加载器会保存到次集合中
7. private List<ContainerProvider> containerProviders = new CopyOnWriteArrayList<ContainerProvider>(); }
Dispatcher的 createConfigurationManager方法
1. protected ConfigurationManager createConfigurationManager(String name) {
2. //name - > struts
3. return new ConfigurationManager(name);
4. }
1.default.properties 属性文件加载器
1. private void init_DefaultProperties() {
2. //保存到ConfigurationManager加载器集合中
3. configurationManager.addConfigurationProvider(new DefaultPropertiesProvider());
4. }
2.创建struts相关文件加载器 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. 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.addConfigurationProvider(createXmlConfigurationProvider(file, false));
13. } else {
14. //struts xml加载器
15. //StrutsXmlConfigurationProvider
16. configurationManager.addConfigurationProvider(createStrutsXmlConfigurationProvider(file, false, servletContext));
17. }
18. } else {
19. throw new IllegalArgumentException("Invalid configuration file name");
20. }
21. }
22. }
23. protected XmlConfigurationProvider createXmlConfigurationProvider(String filename, boolean errorIfMissing) {
24. return new XmlConfigurationProvider(filename, errorIfMissing);
25. }
26. protected XmlConfigurationProvider createStrutsXmlConfigurationProvider(String filename, boolean errorIfMissing, ServletContext ctx) {
27. return new StrutsXmlConfigurationProvider(filename, 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[] classes = 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.addConfigurationProvider(prov);
10. }
11. }
12. }
init_PreloadConfiguration 方法主要完成创建容器, 解析xml动作
1. private Container init_PreloadConfiguration() {
2. //创建Container 解析xml
3. Configuration config = configurationManager.getConfiguration();
4. Container container = 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的getConfiguration 方法
1. public synchronized Configuration getConfiguration() {
2. //创建配置元素管理器
3. if (configuration == null) {
4. // defaultFrameworkBeanName - > struts
5. setConfiguration(createConfiguration(defaultFrameworkBeanName));
6. try {
7. // getContainerProviders 返回注册的各种加载器
8. // reloadContainer 创建Container 解析xml
9. configuration.reloadContainer(getContainerProviders());
10. } catch (ConfigurationException e) {
11. setConfiguration(null);
12. throw 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. return new DefaultConfiguration(beanName);
3. }
DefaultConfiguration的reloadContainer方法 会去执行已注册的各种加载器 ,和创建容器
1. public synchronized List<PackageProvider> reloadContainer(List<ContainerProvider> providers) throws ConfigurationException {
2. packageContexts.clear();
3. loadedFileNames.clear();
4. List<PackageProvider> packageProviders = new ArrayList<PackageProvider>();
5. // 保存struts常量
6. ContainerProperties props = new ContainerProperties();
7. //容器构建器
8. ContainerBuilder builder = new ContainerBuilder();
9. for (final ContainerProvider containerProvider : providers) {
10. /**
11. * 初始化Document 准备解析
12. * 具体在XmlConfigurationProvider实现类 会处理include节点
13. * 处理完成之后Document会保存到XmlConfigurationProvider#documents list集合中
14. * include file路径会保存到XmlConfigurationProvider#loadedFileUrls set集合中
15. * 从代码中发现 include file属性中 可以使用通配符 "*"
16. */
17. /** StrutsXmlConfigurationProvider 是 XmlConfigurationProvider的子类 */
18. /** StrutsXmlConfigurationProvider struts*.xml */
19. containerProvider.init(this);
20. //针对"bean","constant","unknown-handler-stack"节点 不包括"package"节点 解析xml
21. //每一个bean 对应一个LocatableFactory LocatableFactory保存了bean的定义
22. //bean定义 保存到ContainerBuilder#factories map集合中
23. //配置文件中定义的常量 保存到props中
24. containerProvider.register(builder, props);
25. }
26. //将常量保存到ContainerBuilder#factories map集合中
27. //每一个常量对应一个LocatableConstantFactory
28. props.setConstants(builder);
29. builder.factory(Configuration.class, new Factory<Configuration>() {
30. public Configuration create(Context context) throws Exception {
31. return DefaultConfiguration.this;
32. }
33. });
34. ActionContext oldContext = ActionContext.getContext();
35. try {
36. //创建辅助容器 ContainerImpl并且 实例化 struts一些核心类
37. Container bootstrap = createBootstrapContainer();
38. setContext(bootstrap);
39. //主容器 这是一个全局变量
40. container = builder.create(false);
41. setContext(container);
42. objectFactory = container.getInstance(ObjectFactory.class);
43. // Process the configuration providers first
44. for (final ContainerProvider containerProvider : providers) {
45. if (containerProvider instanceof PackageProvider) {
46. //com.opensymphony.xwork2.config.providers.XmlConfigurationProvider#setObjectFactory(ObjectFactory)
47. container.inject(containerProvider);
48. //解析 xml package节点
49. //保存packageContexts map集合中
50. //com.opensymphony.xwork2.config.providers.XmlConfigurationProvider line 481 ((PackageProvider) containerProvider).loadPackages();
51. packageProviders.add((PackageProvider) containerProvider);
52. }
53. }
54. // Then process any package providers from the plugins
55. Set<String> packageProviderNames = container.getInstanceNames(PackageProvider.class); if (packageProviderNames != null) {
56. for (String name : packageProviderNames) {
57. PackageProvider provider = container.getInstance(PackageProvider.class, name);
58. provider.init(this);
59. provider.loadPackages();
60. packageProviders.add(provider);
61. }
62. }
63. //TODO
64. rebuildRuntimeConfiguration();
65. } finally {
66. if (oldContext == null) {
67. ActionContext.setContext(null);
68. }
69. }
70. return packageProviders;
71. }
StrutsXmlConfigurationProvider的init方法 具体在父类XmlConfigurationProvider中实现
1. public void init(Configuration configuration) {
2. this.configuration = configuration;
3. this.includedFileNames = configuration.getLoadedFileNames();
4. // configFileName ->struts.xml
5. //1.递归处理include节点
6. //2.生成Document 集合
7. loadDocuments(configFileName);
8. }
loadDocuments方法中调用了loadConfigurationFiles方法 返回一个Document集合
1. private void loadDocuments(String configFileName) {
2. loadedFileUrls.clear();
3. //List<Document> documents
4. documents = loadConfigurationFiles(configFileName, null);
5. }
loadConfigurationFiles方法 递归处理include节点 最终生成Document集合
1. private List<Document> loadConfigurationFiles(String fileName, Element includeElement) {
2. List<Document> docs = new ArrayList<Document>();
3. List<Document> finalDocs = new ArrayList<Document>();
4. //防止include重复引入
5. if (!includedFileNames.contains(fileName)) {
6. if (LOG.isDebugEnabled()) {
7. LOG.debug("Loading action configurations from: " + fileName);
8. }
9. includedFileNames.add(fileName);
10. Iterator<URL> urls = null;
11. InputStream is = null;
12. IOException ioException = null;
13. try {
14. urls = getConfigurationUrls(fileName);
15. } catch (IOException ex) {
16. ioException = ex;
17. }
18. if (urls == null || !urls.hasNext()) {
19. if (errorIfMissing) {
20. throw new ConfigurationException("Could not open files of the name " + fileName, ioException); }
展开阅读全文