struts2源码分析-初始化流程
这一篇文章主要是记录struts.xml的初始化,还原struts2.xml的初始化流程。源码依据struts2-2.3.16.3版本。
struts2初始化入口,位于web.xml中:
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
</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文件的:
private void init_TraditionalXmlConfigurations() {
String configPaths = initParams.get("config");
if (configPaths == null) {
configPaths = DEFAULT_CONFIGURATION_PATHS;//DEFAULT_CONFIGURATION_PATHS = "struts-default.xml,struts-plugin.xml,struts.xml",即默认需要初始化这三个配置文件。
}
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");
}
}
}
默认根据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配置的时候就会把配置初始化出来:
Container container = init_PreloadConfiguration();
private Container init_PreloadConfiguration() {
Configuration config = configurationManager.getConfiguration();
Container container = config.getContainer();
boolean reloadi18n = Boolean.valueOf(container.getInstance(String.class, StrutsConstants.STRUTS_I18N_RELOAD));
LocalizedTextUtil.setReloadBundles(reloadi18n);
ContainerHolder.store(container);
return container;
}
configurationManager.getConfiguration()的作用是根据配置将configuration对象实例化,并根据当前的container将内容填充:
public synchronized Configuration getConfiguration() {
if (configuration == null) {
setConfiguration(createConfiguration(defaultFrameworkBeanName));
try {
configuration.reloadContainer(getContainerProviders());
} catch (ConfigurationException e) {
setConfiguration(null);
throw new ConfigurationException("Unable to load configuration.", e);
}
} else {
conditionalReload();
}
return configuration;
}
调用每个providers的register方法解析制定的xml,此处的providers即包含前面在init_TraditionalXmlConfigurations中初始化的struts-default.xml,struts-plugin.xml,struts.xml的三个providers。
public synchronized List<PackageProvider> reloadContainer(List<ContainerProvider> providers) throws ConfigurationException {
packageContexts.clear();
loadedFileNames.clear();
List<PackageProvider> packageProviders = new ArrayList<PackageProvider>();
ContainerProperties props = new ContainerProperties();
ContainerBuilder builder = new ContainerBuilder();
Container bootstrap = createBootstrapContainer(providers);
for (final ContainerProvider containerProvider : providers)
{
bootstrap.inject(containerProvider);
containerProvider.init(this);
containerProvider.register(builder, props);
}
继续向下看StrutsXmlConfigurationProvider.register方法,可以看到关键逻辑是在父类里面:
StrutsXmlConfigurationProvider.java
public void register(ContainerBuilder containerBuilder, LocatableProperties props) throws ConfigurationException {
if (servletContext != null && !containerBuilder.contains(ServletContext.class)) {
containerBuilder.factory(ServletContext.class, new Factory<ServletContext>() {
public ServletContext create(Context context) throws Exception {
return servletContext;
}
});
}
super.register(containerBuilder, props);
}
这里将在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定义
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 ("package".equals(nodeName)) {
PackageConfig cfg = addPackage(child);
if (cfg.isNeedsRefresh()) {
reloads.add(child);
}
}
}
}
loadExtraConfiguration(doc);
}
struts2源码分析-初始化流程的更多相关文章
- Struts2 源码分析——Action代理类的工作
章节简言 上一章笔者讲到关于如何加载配置文件里面的package元素节点信息.相信读者到这里心里面对struts2在启动的时候加载相关的信息有了一定的了解和认识.而本章将讲到关于struts2启动成功 ...
- Struts2 源码分析——配置管理之PackageProvider接口
本章简言 上一章讲到关于ContainerProvider的知识.让我们知道struts2是如何注册相关的数据.也知道如何加载相关的配置信息.本章笔者将讲到如何加载配置文件里面的package元素节点 ...
- Struts2 源码分析——配置管理之ContainerProvider接口
本章简言 上一章笔者讲到关于Dispatcher类的执行action功能,知道了关于执行action需要用到的信息.而本章将会讲到的内容也跟Dispatcher类有关系.那就是配置管理中的Contai ...
- Struts2 源码分析——调结者(Dispatcher)之执行action
章节简言 上一章笔者写关于Dispatcher类如何处理接受来的request请求.当然读者们也知道他并非正真的执行action操作.他只是在执行action操作之前的准备工作.那么谁才是正真的执行a ...
- Struts2 源码分析——过滤器(Filter)
章节简言 上一章笔者试着建一个Hello world的例子.是一个空白的struts2例子.明白了运行struts2至少需要用到哪一些Jar包.而这一章笔者将根据前面章节(Struts2 源码分析—— ...
- Struts2 源码分析——DefaultActionInvocation类的执行action
本章简言 上一章讲到关于拦截器的机制的知识点,让我们对拦截器有了一定的认识.我们也清楚的知道在执行用户action类实例之前,struts2会先去执行当前action类对应的拦截器.而关于在哪里执行a ...
- Struts2 源码分析——拦截器的机制
本章简言 上一章讲到关于action代理类的工作.即是如何去找对应的action配置信息,并执行action类的实例.而这一章笔者将讲到在执行action需要用到的拦截器.为什么要讲拦截器呢?可以这样 ...
- Struts2 源码分析——Hello world
新建第一个应用程序 上一章我们讲到了关于struts2核心机制.对于程序员来讲比较概念的一章.而本章笔者将会亲手写一个Hello world的例子.所以如果对struts2使用比较了解的朋友,请跳过本 ...
- apiserver源码分析——启动流程
前言 apiserver是k8s控制面的一个组件,在众多组件中唯一一个对接etcd,对外暴露http服务的形式为k8s中各种资源提供增删改查等服务.它是RESTful风格,每个资源的URI都会形如 / ...
随机推荐
- Linux -- cal/bc/LANGE与帮助文档
cal 显示日历命令 使用cal命令,显示日历 cal [month] [year] 1.显示当前的日历 [root@localhost ~]# cal 一月 日 一 二 三 四 五 六 2.显示指定 ...
- luajit 64位 for cocos2dx 编译ios解决方法
最近luajit发布了64位beta版,由于appstore上线必须是64位的应用,而且我的游戏项目用到lua脚本,所以必须要用到64位的luajit来编译lua脚本. 方法如下: 在luajit官网 ...
- 丑数(Ugly Numbers, UVa 136)
丑数(Ugly Numbers, UVa 136) 题目描述 我们把只包含因子2.3和5的数称作丑数(Ugly Number).求按从小到大的顺序的第1500个丑数.例如6.8都是丑数,但14不是,因 ...
- 剑指Offer_编程题之替换空格
题目描述 请实现一个函数,将一个字符串中的空格替换成“%20”.例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy.
- MySQL常用参数说明(持续更新)
##innodb correlate innodb_flush_log_at_trx_commit value: 0,[1],2 effect: control the flush opera ...
- 常用模块 - shutil模块
一.简介 shutil – Utility functions for copying and archiving files and directory trees.(用于复制和存档文件和目录树的实 ...
- 配置一个nginx反向代理&负载均衡服务器
一.基本信息 系统(L):CentOS 6.9 #下载地址:http://mirrors.sohu.com 反代&负载均衡(N):NGINX 1.14.0 #下载地址:http://nginx ...
- PHP文档生成器(PHPDoc)的基本用法
目录 PHP文档生成器(PHPDoc)的基本用法 PHPDoc概述 安装 PHPDoc注释规范 页面级别的注释 代码级别的注释 生成API文档 额外软件 PHP文档生成器(PHPDoc)的基本用法 P ...
- Debian中CodeIgniter+nginx+MariaDB+phpMyAdmin配置
本文不讲述软件安装过程,记述本人在Debia中配置CodeIgniter时遇到的问题及解决方法,希望能够为有需要的人提供帮助. 一.Debian版本及所需的软件 Debian 9.8 stretch ...
- tp js结合时间戳
$(document).ready(function(){ $.extend({ show:function(){ } }); setInterval("show()",1000) ...