Tomcat Web目录部署
2018-11-10 本文已影响61人
晴天哥_王志
开篇
这篇文章主要针对Tomcat针对Web目录部署进行一些常用的逻辑判断,这部分的核心逻辑主要回答了以下几个问题(这部分其实说实话我也不是特别明白)。
- 1、Context对象的创建。
- 2、配置变更重新部署的前置处理。
- 3、核心逻辑在于Context启动过程,但是这部分后面由单独的文章进行说明。
部署过程
-
1、对于Host的appBase目录下所有符合条件的目录,由线程池完成部署。
-
2、针对每个目录,按照如下逻辑进行判断:
-
条件判断一:如果Host的deployXML属性值为true,并且存在META-INF/context.xml文件,则由Digester解析content.xml文件创建Context对象。
-
条件判断二:如果Host的deployXML属性值为false,但是存在META-INF/context.xml文件,则构造FailedContext对象。
-
条件判断三:其他情况下根据Host的contextClass属性指定的类型创建Context对象,如不指定则为org.apache.catalina.core.StandardContext。
-
-
3、为Context实例添加ContextConfig生命周期监听器。
-
4、通过Host的addChild()方法将Context实例对象添加到Host,该方法会判断Host是否启动,如果已启动则直接启动Context对象。Context的启动过程才是核心逻辑,后面会单独有文章进行说明。
-
5、将Context描述文件、Web应用目录及web.xml等添加到守护资源,以便文件发生变更时重新部署或者加载web应用。
源码解析
public class HostConfig implements LifecycleListener {
protected void deployDirectory(ContextName cn, File dir) {
// step1、针对Web目录进行部署
Context context = null;
// ApplicationContextXml = "META-INF/context.xml"
File xml = new File(dir, Constants.ApplicationContextXml);
File xmlCopy =
new File(host.getConfigBaseFile(), cn.getBaseName() + ".xml");
DeployedApplication deployedApp;
boolean copyThisXml = isCopyXML();
boolean deployThisXML = isDeployThisXML(dir, cn);
try {
// 条件判断一:如果Host的deployXML属性值为true,
// 并且存在META-INF/context.xml文件,
// 则由Digester解析content.xml文件创建Context对象。
if (deployThisXML && xml.exists()) {
synchronized (digesterLock) {
try {
context = (Context) digester.parse(xml);
} catch (Exception e) {
log.error(sm.getString(
"hostConfig.deployDescriptor.error",
xml), e);
context = new FailedContext();
} finally {
digester.reset();
if (context == null) {
context = new FailedContext();
}
}
}
if (copyThisXml == false && context instanceof StandardContext) {
// Host is using default value. Context may override it.
copyThisXml = ((StandardContext) context).getCopyXML();
}
if (copyThisXml) {
Files.copy(xml.toPath(), xmlCopy.toPath());
context.setConfigFile(xmlCopy.toURI().toURL());
} else {
context.setConfigFile(xml.toURI().toURL());
}
// 条件判断二:如果Host的deployXML属性值为false,
// 但是存在META-INF/context.xml文件,则构造FailedContext对象。
} else if (!deployThisXML && xml.exists()) {
// Block deployment as META-INF/context.xml may contain security
// configuration necessary for a secure deployment.
log.error(sm.getString("hostConfig.deployDescriptor.blocked",
cn.getPath(), xml, xmlCopy));
context = new FailedContext();
} else {
// 条件判断三:其他情况下根据Host的contextClass属性指定的类型创建Context对象,
// 如不指定则为org.apache.catalina.core.StandardContext。
context = (Context) Class.forName(contextClass).getConstructor().newInstance();
}
// step2、为Context实例添加ContextConfig生命周期监听器。
Class<?> clazz = Class.forName(host.getConfigClass());
LifecycleListener listener = (LifecycleListener) clazz.getConstructor().newInstance();
context.addLifecycleListener(listener);
context.setName(cn.getName());
context.setPath(cn.getPath());
context.setWebappVersion(cn.getVersion());
context.setDocBase(cn.getBaseName());
// 通过Host的addChild()方法将Context实例对象添加到Host,
// 该方法会判断Host是否启动,如果已启动则直接启动Context对象。
host.addChild(context);
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
log.error(sm.getString("hostConfig.deployDir.error",
dir.getAbsolutePath()), t);
} finally {
// step3、将Context描述文件、Web应用目录及web.xml等添加到守护资源,
// 以便文件发生变更时重新部署或者加载web应用。
deployedApp = new DeployedApplication(cn.getName(),
xml.exists() && deployThisXML && copyThisXml);
deployedApp.redeployResources.put(dir.getAbsolutePath() + ".war",
Long.valueOf(0));
deployedApp.redeployResources.put(dir.getAbsolutePath(),
Long.valueOf(dir.lastModified()));
if (deployThisXML && xml.exists()) {
if (copyThisXml) {
deployedApp.redeployResources.put(
xmlCopy.getAbsolutePath(),
Long.valueOf(xmlCopy.lastModified()));
} else {
deployedApp.redeployResources.put(
xml.getAbsolutePath(),
Long.valueOf(xml.lastModified()));
deployedApp.redeployResources.put(
xmlCopy.getAbsolutePath(),
Long.valueOf(0));
}
} else {
deployedApp.redeployResources.put(
xmlCopy.getAbsolutePath(),
Long.valueOf(0));
if (!xml.exists()) {
deployedApp.redeployResources.put(
xml.getAbsolutePath(),
Long.valueOf(0));
}
}
addWatchedResources(deployedApp, dir.getAbsolutePath(), context);
addGlobalRedeployResources(deployedApp);
}
deployed.put(cn.getName(), deployedApp);
}
}