struts2源码分析-初始化流程

  这一篇文章主要是记录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.xml
            init_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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值