这一篇文章主要是记录struts.xml的初始化,还原struts2.xml的初始化流程。源码依据struts2-2.3.16.3版本。

  struts2初始化入口,位于web.xml中:

1     <filter>
2         <filter-name>struts2</filter-name>
3         <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
4     </filter>

  调用StrutsPrepareAndExecuteFilterinit(FilterConfig filterConfig)方法,进行初始化:

public void init(FilterConfig filterConfig) throws ServletException {InitOperations init = new InitOperations(); Dispatcher dispatcher = null;try {FilterHostConfig config = new FilterHostConfig(filterConfig);init.initLogging(config); dispatcher = init.initDispatcher(config);init.initStaticContentLoader(config, dispatcher);prepare = new PrepareOperations(filterConfig.getServletContext(), dispatcher);execute = new ExecuteOperations(filterConfig.getServletContext(), dispatcher);this.excludedPatterns = init.buildExcludedPatternsList(dispatcher);postInit(dispatcher, filterConfig);} finally {if (dispatcher != null) {dispatcher.cleanUpAfterInit();}init.cleanup();}}

  InitOperations定义了初始化的实现,提供struts2初始化的各个部件的构建过程,包括:logger、dispatcher、static content loader 。我们这里只关心dispatcher的初始化流程。

  dispather的init过程被分解了多个步骤:

            init_FileManager();init_DefaultProperties(); // [1]init_TraditionalXmlConfigurations(); // [2]//初始化struts.xmlinit_LegacyStrutsProperties(); // [3]init_CustomConfigurationProviders(); // [5]init_FilterInitParameters() ; // [6]init_AliasStandardObjects() ; // [7]

  其中第2个步骤:init_TraditionalXmlConfigurations();就是准备初始化xml文件的: 

 1   private void init_TraditionalXmlConfigurations() {
 2         String configPaths = initParams.get("config");
 3         if (configPaths == null) {
 4             configPaths = DEFAULT_CONFIGURATION_PATHS;//DEFAULT_CONFIGURATION_PATHS = "struts-default.xml,struts-plugin.xml,struts.xml",即默认需要初始化这三个配置文件。
 5         }
 6         String[] files = configPaths.split("\\s*[,]\\s*");
 7         for (String file : files) {
 8             if (file.endsWith(".xml")) {
 9                 if ("xwork.xml".equals(file)) {
10                     configurationManager.addContainerProvider(createXmlConfigurationProvider(file, false));
11                 } else {
12                     configurationManager.addContainerProvider(createStrutsXmlConfigurationProvider(file, false, servletContext));
13                 }
14             } else {
15                 throw new IllegalArgumentException("Invalid configuration file name");
16             }
17         }
18     }

  默认根据struts-default.xml,struts-plugin.xml,struts.xml (可根据init-param:config 修改加载路径) 分别创建三个 org.apache.struts2.config. StrutsXmlConfigurationProvider,其中方法register实现默认会从相应配置文件读取props加载到setting 中,会将bean放入ContainerBuilder中,最后将三个containerProviders并加入containerProviders。

  全部的providers准备好后,preLoad配置的时候就会把配置初始化出来:

 1     Container container = init_PreloadConfiguration();
 2
 3
 4  private Container init_PreloadConfiguration() {
 5         Configuration config = configurationManager.getConfiguration();
 6         Container container = config.getContainer();
 7
 8         boolean reloadi18n = Boolean.valueOf(container.getInstance(String.class, StrutsConstants.STRUTS_I18N_RELOAD));
 9         LocalizedTextUtil.setReloadBundles(reloadi18n);
10
11         ContainerHolder.store(container);
12
13         return container;
14     }

  configurationManager.getConfiguration()的作用是根据配置将configuration对象实例化,并根据当前的container将内容填充:  

 1  public synchronized Configuration getConfiguration() {
 2         if (configuration == null) {
 3             setConfiguration(createConfiguration(defaultFrameworkBeanName));
 4             try {
 5                 configuration.reloadContainer(getContainerProviders());
 6             } catch (ConfigurationException e) {
 7                 setConfiguration(null);
 8                 throw new ConfigurationException("Unable to load configuration.", e);
 9             }
10         } else {
11             conditionalReload();
12         }
13
14         return configuration;
15     }

    调用每个providers的register方法解析制定的xml,此处的providers即包含前面在init_TraditionalXmlConfigurations中初始化的struts-default.xml,struts-plugin.xml,struts.xml的三个providers。

 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
 6         ContainerProperties props = new ContainerProperties();
 7         ContainerBuilder builder = new ContainerBuilder();
 8         Container bootstrap = createBootstrapContainer(providers);
 9         for (final ContainerProvider containerProvider : providers)
10         {
11             bootstrap.inject(containerProvider);
12             containerProvider.init(this);
13             containerProvider.register(builder, props);
14         }

  继续向下看StrutsXmlConfigurationProvider.register方法,可以看到关键逻辑是在父类里面:  

 1 StrutsXmlConfigurationProvider.java
 2     public void register(ContainerBuilder containerBuilder, LocatableProperties props) throws ConfigurationException {
 3         if (servletContext != null && !containerBuilder.contains(ServletContext.class)) {
 4             containerBuilder.factory(ServletContext.class, new Factory<ServletContext>() {
 5                 public ServletContext create(Context context) throws Exception {
 6                     return servletContext;
 7                 }
 8             });
 9         }
10         super.register(containerBuilder, props);
11     }

   这里将在xml文件中定义的bean、contants、unknown-handler-stack 元素取出来并加载到容器中去。

 for (Document doc : documents) {Element rootElement = doc.getDocumentElement();NodeList children = rootElement.getChildNodes();int childSize = children.getLength();for (int i = 0; i < childSize; i++) {Node childNode = children.item(i);if (childNode instanceof Element) {Element child = (Element) childNode;final String nodeName = child.getNodeName();if ("bean".equals(nodeName)) {} else if ("constant".equals(nodeName)) {} else if (nodeName.equals("unknown-handler-stack")) {}}}
}

  loadPackages负责初始化struts2 pacakge定义

 1  for (Document doc : documents) {
 2     Element rootElement = doc.getDocumentElement();
 3     NodeList children = rootElement.getChildNodes();
 4     int childSize = children.getLength();
 5
 6     for (int i = 0; i < childSize; i++) {
 7         Node childNode = children.item(i);
 8
 9         if (childNode instanceof Element) {
10             Element child = (Element) childNode;
11
12             final String nodeName = child.getNodeName();
13
14             if ("package".equals(nodeName)) {
15                 PackageConfig cfg = addPackage(child);
16                 if (cfg.isNeedsRefresh()) {
17                     reloads.add(child);
18                 }
19             }
20         }
21     }
22     loadExtraConfiguration(doc);
23 }

  

  

转载于:https://www.cnblogs.com/jason0529/p/4117217.html

struts2源码分析-初始化流程相关推荐

  1. 【Android 启动过程】Activity 启动源码分析 ( ActivityThread 流程分析 二 )

    文章目录 前言 一.ActivityManagerService.attachApplicationLocked 二.ActivityStackSupervisor.attachApplication ...

  2. Struts2 源码分析——拦截器的机制

    本章简言 上一章讲到关于action代理类的工作.即是如何去找对应的action配置信息,并执行action类的实例.而这一章笔者将讲到在执行action需要用到的拦截器.为什么要讲拦截器呢?可以这样 ...

  3. FairFuzz 论文简读+源码分析+整体流程简述

    FairFuzz: A Targeted Mutation Strategy for Increasing Greybox Fuzz Testing Coverage 一.论文阅读 Abstract ...

  4. mybatis源码分析执行流程

    前言 在上一篇,我们了解了mybatis的整体执行流程,以及内部的各个组件在执行过程中的功能,下面我们来通过源码的方式对其中比较重要的几个组件在执行过程的使用进行简单的分析与说明 环境准备 基于第一篇 ...

  5. uboot 2021.10源码分析(启动流程)

    uboot版本:2021.10 平台:armv8  rk3399  eMMC 16G  LPDDR4 4G 本文主要基于uboot的执行流程进行分析而忽略了相关细节,从uboot的基本框架结构着手,新 ...

  6. mybatis 源码分析, 初始化

    分析版本 我们先分析xml配置文件形式的 mybatis, 等我们分析完毕了, 可以去分析 mybatis 和 spring 的对接 pom.xml <dependency><gro ...

  7. tomcat源码分析--初始化与启动

    2019独角兽企业重金招聘Python工程师标准>>> 摘要: 在阅读tomcat源码前,我们一般都会有如下几个疑问: - web容器和servlet容器的区别是什么: - 在spr ...

  8. 【Android 启动过程】Activity 启动源码分析 ( ActivityThread 流程分析 一 )

    文章目录 一.ActivityThread 主函数启动 二.ActivityThread 绑定 ApplicationThread 三.AMS attachApplication -> atta ...

  9. 1月24日学习内容整理:Django的admin组件源码分析及流程

    一.单例模式 单例模式(Singleton Pattern)是一种常用的软件设计模式,该模式的主要目的是确保某一个类只有一个实例存在.当你希望在整个系统中,某个类只能出现一个实例时,单例对象就能派上用 ...

最新文章

  1. java 文件拷贝保留原来的属性,Java - 复制JPG,同时保留所有文件属性
  2. 配置bond和vlan
  3. #!/bin/sh与#!/bin/bash的区别
  4. oracle表的管理,Oracle表的管理
  5. 职场伦语-感悟职场,分享心得
  6. android studio 便携式wlan热点 网络名称_速存 | WLAN信号增强器
  7. linux控制主机风扇转速,怎么调整cpu风扇转速 cpu风扇转速调整方法【详解】
  8. html页面点击生成图片并可以下载图片
  9. 前端播放flv的视频
  10. 老男孩教育运维班100台规模集群全网数据备份项目上机实战
  11. IDEA修改运行内存
  12. 欢迎大家加入Xcode公社
  13. java检索电脑的所有图片_查找电脑里重复的照片
  14. 高级软件工程师必备的五大技能
  15. 使用canvas画网格
  16. usaco-5.1-fc-passed
  17. Three.js加载外部模型骨骼动画
  18. node.js安装步骤
  19. 14 Tornado - XSRF
  20. 电脑启动时显示windows无法正常启动怎么解决

热门文章

  1. mybatis-generator
  2. linux查看log日志在哪,如何查看linux的系统log日志
  3. oracle存储过程数量,Oracle:存储过程的可变参数数量
  4. 循环遍历java属性_java中循环遍历实体类的属性和数据类型以及属性值
  5. Python入门--字符串的比较
  6. [leetcode] 472. 连接词
  7. 蛮力法 —— 求解最大连续子序列和问题
  8. 二层交换:网桥(交换机)
  9. 单纯型法Ⅱ(bzoj 1061: [Noi2008]志愿者招募)
  10. 2017百度之星初赛:A-1006. 度度熊的01世界(DFS)