HostConfig.deployApps()
//在监听到start事件类型,也就是StandardHost调用startInternal
protected void deployApps() { File appBase = host.getAppBaseFile();
//这个值是在触发before_start时间时生成的,默认是tomcat安装目录+engine名+host名
File configBase = host.getConfigBaseFile();
//获取host上配置的webapp下的所有文件,默认是webapps目录下的所有文件
String[] filteredAppPaths = filterAppPaths(appBase.list());
// Deploy XML descriptors from configBase 发布xml描述文件
deployDescriptors(configBase, configBase.list());
// Deploy WARs
deployWARs(appBase, filteredAppPaths);
// Deploy expanded folders
deployDirectories(appBase, filteredAppPaths); } deployWARs protected void deployWARs(File appBase, String[] files) { if (files == null)
return; ExecutorService es = host.getStartStopExecutor();
List<Future<?>> results = new ArrayList<>(); for (int i = 0; i < files.length; i++) { if (files[i].equalsIgnoreCase("META-INF"))
continue;
if (files[i].equalsIgnoreCase("WEB-INF"))
continue;
File war = new File(appBase, files[i]);
//处理war
if (files[i].toLowerCase(Locale.ENGLISH).endsWith(".war") &&
war.isFile() && !invalidWars.contains(files[i]) ) { ContextName cn = new ContextName(files[i], true); if (isServiced(cn.getName())) {
continue;
}
//如果已经发布
if (deploymentExists(cn.getName())) {
DeployedApplication app = deployed.get(cn.getName());
boolean unpackWAR = unpackWARs;
if (unpackWAR && host.findChild(cn.getName()) instanceof StandardContext) {
unpackWAR = ((StandardContext) host.findChild(cn.getName())).getUnpackWAR();
}
//如果不需要解压,并且已经发布。那么判断对应的docBase是否已经存在
if (!unpackWAR && app != null) {
// Need to check for a directory that should not be
// there
File dir = new File(appBase, cn.getBaseName());
if (dir.exists()) {
if (!app.loggedDirWarning) {
log.warn(sm.getString(
"hostConfig.deployWar.hiddenDir",
dir.getAbsoluteFile(),
war.getAbsoluteFile()));
app.loggedDirWarning = true;
}
} else {
app.loggedDirWarning = false;
}
}
continue;
} // Check for WARs with /../ /./ or similar sequences in the name
if (!validateContextPath(appBase, cn.getBaseName())) {
log.error(sm.getString(
"hostConfig.illegalWarName", files[i]));
invalidWars.add(files[i]);
continue;
} results.add(es.submit(new DeployWar(this, cn, war)));
}
} for (Future<?> result : results) {
try {
result.get();
} catch (Exception e) {
log.error(sm.getString(
"hostConfig.deployWar.threaded.error"), e);
}
}
} HostConfig.deployWAR(cn, war); protected void deployWAR(ContextName cn, File war) { // Constants.ApplicationContextXml == META-INF/context.xml
File xml = new File(host.getAppBaseFile(),
cn.getBaseName() + "/" + Constants.ApplicationContextXml); File warTracker = new File(host.getAppBaseFile(), cn.getBaseName() + Constants.WarTracker); boolean xmlInWar = false;
try (JarFile jar = new JarFile(war)) {
JarEntry entry = jar.getJarEntry(Constants.ApplicationContextXml);
//判断是否有context.xml在jar包里面
if (entry != null) {
xmlInWar = true;
}
} catch (IOException e) {
/* Ignore */
} // If there is an expanded directory then any xml in that directory
// should only be used if the directory is not out of date and
// unpackWARs is true. Note the code below may apply further limits
boolean useXml = false;
// If the xml file exists then expandedDir must exists so no need to
// test that here
//如果对应xml存在,并且允许解压,也就是已经解压了,这个war包没有修改过
if (xml.exists() && unpackWARs &&
(!warTracker.exists() || warTracker.lastModified() == war.lastModified())) {
useXml = true;
} Context context = null;
//是否需要发布这个context.xml,通过校验
boolean deployThisXML = isDeployThisXML(war, cn); try {
//允许发布这个xml并且仅仅是使用xml并且不允许copyxml到配置目录,如果允许copy到配置目录,那么这个xml可能不是最新的。
if (deployThisXML && useXml && !copyXML) {
synchronized (digesterLock) {
try {
context = (Context) digester.parse(xml);
} catch (Exception e) {
log.error(sm.getString(
"hostConfig.deployDescriptor.error",
war.getAbsolutePath()), e);
} finally {
digester.reset();
if (context == null) {
context = new FailedContext();
}
}
}
//设置context.xml配置文件
context.setConfigFile(xml.toURI().toURL());
//允许发布这个context.xml并且这个xml在war包里面
} else if (deployThisXML && xmlInWar) {
synchronized (digesterLock) {
try (JarFile jar = new JarFile(war)) {
JarEntry entry = jar.getJarEntry(Constants.ApplicationContextXml);
try (InputStream istream = jar.getInputStream(entry)) {
context = (Context) digester.parse(istream);
}
} catch (Exception e) {
log.error(sm.getString(
"hostConfig.deployDescriptor.error",
war.getAbsolutePath()), e);
} finally {
digester.reset();
if (context == null) {
context = new FailedContext();
}
context.setConfigFile(
UriUtil.buildJarUrl(war, Constants.ApplicationContextXml));
}
}
//不允许发布这个context.xml并且这个xml在war包里面的,那么就直接new出一个StandardContext
} else if (!deployThisXML && xmlInWar) {
// 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(), Constants.ApplicationContextXml,
new File(host.getConfigBaseFile(), cn.getBaseName() + ".xml")));
} else {
context = (Context) Class.forName(contextClass).getConstructor().newInstance();
}
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
log.error(sm.getString("hostConfig.deployWar.error",
war.getAbsolutePath()), t);
} finally {
if (context == null) {
context = new FailedContext();
}
} boolean copyThisXml = false;//是否需要复制xml到配置文件夹中
if (deployThisXML) {//允许发布
if (host instanceof StandardHost) {
copyThisXml = ((StandardHost) host).isCopyXML();
} // If Host is using default value Context can override it. context指定的copyXml属性可以覆盖host级别的
if (!copyThisXml && context instanceof StandardContext) {
copyThisXml = ((StandardContext) context).getCopyXML();
}
//如果context.xml在war中,并且允许复制这个xml到配置路径,那么就将此context.xml复制到配置文件夹中
if (xmlInWar && copyThisXml) {
// Change location of XML file to config base
xml = new File(host.getConfigBaseFile(),
cn.getBaseName() + ".xml");
try (JarFile jar = new JarFile(war)) {
JarEntry entry = jar.getJarEntry(Constants.ApplicationContextXml);
try (InputStream istream = jar.getInputStream(entry);
FileOutputStream fos = new FileOutputStream(xml);
BufferedOutputStream ostream = new BufferedOutputStream(fos, 1024)) {
byte buffer[] = new byte[1024];
while (true) {
int n = istream.read(buffer);
if (n < 0) {
break;
}
ostream.write(buffer, 0, n);
}
ostream.flush();
}
} catch (IOException e) {
/* Ignore */
}
}
}
//下面这部分代码基本和deployDescriptors差不多
DeployedApplication deployedApp = new DeployedApplication(cn.getName(),
xml.exists() && deployThisXML && copyThisXml); long startTime = 0;
// Deploy the application in this WAR file
if(log.isInfoEnabled()) {
startTime = System.currentTimeMillis();
log.info(sm.getString("hostConfig.deployWar",
war.getAbsolutePath()));
} try {
// Populate redeploy resources with the WAR file
deployedApp.redeployResources.put
(war.getAbsolutePath(), Long.valueOf(war.lastModified())); if (deployThisXML && xml.exists() && copyThisXml) {
//这个xml被复制到配置目录
deployedApp.redeployResources.put(xml.getAbsolutePath(),
Long.valueOf(xml.lastModified()));
} else {
// In case an XML file is added to the config base later 如果配置加载配置目录中才会有效
deployedApp.redeployResources.put(
(new File(host.getConfigBaseFile(),
cn.getBaseName() + ".xml")).getAbsolutePath(),
Long.valueOf(0));
} 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() + ".war");
host.addChild(context);//与deployDescriptors一样的操作
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
log.error(sm.getString("hostConfig.deployWar.error",
war.getAbsolutePath()), t);
} finally {
// If we're unpacking WARs, the docBase will be mutated after
// starting the context
boolean unpackWAR = unpackWARs;
if (unpackWAR && context instanceof StandardContext) {
unpackWAR = ((StandardContext) context).getUnpackWAR();
}
//上面不是已经添加了docBase资源的监控了吗?这里是因为tomcat在解压了war之后会重新定义它的docBase目录,所以需要添加,不管原始的还是新的都要进行监控
if (unpackWAR && context.getDocBase() != null) {
File docBase = new File(host.getAppBaseFile(), cn.getBaseName());
deployedApp.redeployResources.put(docBase.getAbsolutePath(),
Long.valueOf(docBase.lastModified()));
addWatchedResources(deployedApp, docBase.getAbsolutePath(),
context);
if (deployThisXML && !copyThisXml && (xmlInWar || xml.exists())) {
deployedApp.redeployResources.put(xml.getAbsolutePath(),
Long.valueOf(xml.lastModified()));
}
} else {
// Passing null for docBase means that no resources will be
// watched. This will be logged at debug level.
addWatchedResources(deployedApp, null, context);
}
// Add the global redeploy resources (which are never deleted) at
// the end so they don't interfere with the deletion process
addGlobalRedeployResources(deployedApp);
} deployed.put(cn.getName(), deployedApp); if (log.isInfoEnabled()) {
log.info(sm.getString("hostConfig.deployWar.finished",
war.getAbsolutePath(), Long.valueOf(System.currentTimeMillis() - startTime)));
}
}

最新文章

  1. Android 性能测试
  2. JAVA正则表达式:Pattern类与Matcher类详解(转)
  3. HDU-2196 Computer (树形DP)
  4. 用jmap分析java程序
  5. 解决Cygwin中vim的backspace不能正常使用(转)
  6. 创建dblink遇到一系列问题
  7. (转载)python多行注释
  8. zabbix discovery
  9. java牛人给新人的几点建议
  10. MVC如何在Pipeline中接管请求的?
  11. java的抽象类和抽象方法(注意查看如何调用抽象类中的非抽象方法)
  12. MySQL长短密码
  13. [51nod1743]雪之国度
  14. Core Location实现定位
  15. js中!和!!的区别及用法
  16. ELK部署详解--kibana
  17. 磁盘异步I / O在Windows上显示为同步
  18. 4.1Python数据处理篇之Matplotlib系列(一)---初识Matplotlib
  19. jquery分页插件精选
  20. ios开发之--/System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/bin/ruby: bad interpreter: No such file

热门文章

  1. DNS查询命令
  2. lodop+art-template实现web端漂亮的小票样式打印
  3. Asp.Net Core 项目 EntityFramework Core 根据登录用户名过滤数据
  4. python 之 面向对象基础(定义类、创建对象,名称空间)
  5. Linux常用实用命令
  6. 学习过程中遇到的python内置函数,后续遇到会继续补充进去
  7. 10分钟实现Typora(markdown)编辑器
  8. java创建对象的方式
  9. 移动端布局(viewport)方法
  10. Fire! UVA - 11624 (两步bfs)