前言

当应用配置文件发生变化时,无需重启tomcat,可以使tomcat重新加载应用。

场景

假设存在一个J2EE应用A,对应war文件名称为A.war,部署在tomcat的webapps目录下,即:CATALINA_HOME/webapps/A.war。

tomcat启动之后会将A.war解压,并在$CATALINA_HOME/webapps/目录下对应生成目录A,即:CATALINA_HOME/webapps/A。

此时,需要修改A下存在一个配置文件a_dao.xml,其中配置了一些参数,如:数据库配置。

为了使应用能够重新使用最新的配置属性,有2种方式:

其一:修改配置文件,直接重启tomcat。

其二:修改配置文件,执行命令:touch TOMCAT_HOME/webapps/A/WEB-INF/web.xml,让tomcat重新加载应用A。

原理

当然,修改配置之后重启tomcat这个方式不难理解,应用重新被部署,肯定会使用到最新的配置。

那么,对于不需要重启tomcat,而是让tomcat重新加载应用,低层的实现原理是什么呢?

首先,我们来看通过tomcat重新加载应用,我们做了什么?

我们只做了一件事情:touch TOMCAT_HOME/webapps/A/WEB-INF/web.xml

显然,这里涉及了2个组件:touch命令和tomcat。

OK,下面我们分别解读这2个组件都做了什么事情,拨云见雾地看看这里面都发生了什么。

1.touch命令做了什么

执行了touch命令,这个命令的作用是修改文件的时间戳。

TOUCH(1)                         User Commands                        TOUCH(1)

NAME
touch - change file timestamps SYNOPSIS
touch [OPTION]... FILE... DESCRIPTION
Update the access and modification times of each FILE to the current time. A FILE argument that does not exist is created empty, unless -c or -h is supplied.

什么意思?在实践中发现,touch命令会将文件的“创建时间”,“访问时间”和“修改时间”这三个时间戳都修改为当前时间。

这意味着什么呢?tomcat会认为这个文件发生了变化!

那么,是不是可以理解为一旦tomcat监测到应用的描述文件web.xml发生变化之后就会主动重新加载应用呢?

如下是一个实际的tomcat重新加载应用的输出日志。

九月 15, 2017 8:21:49 下午 org.apache.catalina.startup.HostConfig reload
信息: Reloading context [/test-javaweb]
九月 15, 2017 8:21:49 下午 org.apache.catalina.core.StandardContext reload
信息: Reloading Context with name [/test-javaweb] has started
九月 15, 2017 8:21:49 下午 org.apache.catalina.ha.session.DeltaManager stopInternal
信息: Manager [localhost#/test-javaweb] expiring sessions upon shutdown
九月 15, 2017 8:21:50 下午 org.apache.catalina.startup.TaglibUriRule body
信息: TLD skipped. URI: http://java.sun.com/jstl/core_rt is already defined
九月 15, 2017 8:21:50 下午 org.apache.catalina.startup.TaglibUriRule body
信息: TLD skipped. URI: http://java.sun.com/jstl/core is already defined
九月 15, 2017 8:21:50 下午 org.apache.catalina.startup.TaglibUriRule body
信息: TLD skipped. URI: http://java.sun.com/jsp/jstl/core is already defined
九月 15, 2017 8:21:50 下午 org.apache.catalina.startup.TaglibUriRule body
信息: TLD skipped. URI: http://java.sun.com/jstl/fmt_rt is already defined
九月 15, 2017 8:21:50 下午 org.apache.catalina.startup.TaglibUriRule body
信息: TLD skipped. URI: http://java.sun.com/jstl/fmt is already defined
九月 15, 2017 8:21:50 下午 org.apache.catalina.startup.TaglibUriRule body
信息: TLD skipped. URI: http://java.sun.com/jsp/jstl/fmt is already defined
九月 15, 2017 8:21:50 下午 org.apache.catalina.startup.TaglibUriRule body
信息: TLD skipped. URI: http://java.sun.com/jsp/jstl/functions is already defined
九月 15, 2017 8:21:50 下午 org.apache.catalina.startup.TaglibUriRule body
信息: TLD skipped. URI: http://jakarta.apache.org/taglibs/standard/permittedTaglibs is already defined
九月 15, 2017 8:21:50 下午 org.apache.catalina.startup.TaglibUriRule body
信息: TLD skipped. URI: http://jakarta.apache.org/taglibs/standard/scriptfree is already defined
九月 15, 2017 8:21:50 下午 org.apache.catalina.startup.TaglibUriRule body
信息: TLD skipped. URI: http://java.sun.com/jstl/sql_rt is already defined
九月 15, 2017 8:21:50 下午 org.apache.catalina.startup.TaglibUriRule body
信息: TLD skipped. URI: http://java.sun.com/jstl/sql is already defined
九月 15, 2017 8:21:50 下午 org.apache.catalina.startup.TaglibUriRule body
信息: TLD skipped. URI: http://java.sun.com/jsp/jstl/sql is already defined
九月 15, 2017 8:21:50 下午 org.apache.catalina.startup.TaglibUriRule body
信息: TLD skipped. URI: http://java.sun.com/jstl/xml_rt is already defined
九月 15, 2017 8:21:50 下午 org.apache.catalina.startup.TaglibUriRule body
信息: TLD skipped. URI: http://java.sun.com/jstl/xml is already defined
九月 15, 2017 8:21:50 下午 org.apache.catalina.startup.TaglibUriRule body
信息: TLD skipped. URI: http://java.sun.com/jsp/jstl/xml is already defined
九月 15, 2017 8:21:50 下午 org.chench.test.web.listener.TestWebListener contextInitialized
信息: TestWebListener contextInitialized
九月 15, 2017 8:21:50 下午 org.chench.test.web.filter.TestWebFilter init
信息: TestWebFilter context path=/test-javaweb
九月 15, 2017 8:21:50 下午 org.apache.catalina.core.StandardContext reload
信息: Reloading Context with name [/test-javaweb] is completed

经过实验发现,一旦web应用的web.xml文件的时间戳发生变化(创建时间,修改时间或访问时间发生变化),tomcat就会重新加载应用。

2.tomcat如何知道应用的web.xml发生了变化

在上述tomcat日志中存在如下信息:

九月 15, 2017 8:21:49 下午 org.apache.catalina.startup.HostConfig reload
信息: Reloading context [/test-javaweb]

追踪tomcat源码发现,这个日志信息是在org.apache.catalina.startup.HostConfig类的reload方法中打印的:

/*
* Note: If either of fileToRemove and newDocBase are null, both will be
* ignored.
*/
private void reload(DeployedApplication app, File fileToRemove, String newDocBase) {
if(log.isInfoEnabled())
log.info(sm.getString("hostConfig.reload", app.name));
...
}

继续追踪tomcat源码发现,在org.apache.catalina.core.ContainerBase中存在如下实现:

    /**
* Start the background thread that will periodically check for
* session timeouts.
*/
protected void threadStart() { if (thread != null)
return;
if (backgroundProcessorDelay <= 0)
return; threadDone = false;
String threadName = "ContainerBackgroundProcessor[" + toString() + "]";
thread = new Thread(new ContainerBackgroundProcessor(), threadName);
thread.setDaemon(true);
thread.start(); }

也就是说,Tomcat在启动时会启动一个后台线程ContainerBackgroundProcessor,用于监控web应用的配置变化。

默认情况下,该线程会每隔10秒检查一次web应用的web.xml文件的变化。

该值在server.xml中Engine元素上配置属性:backgroundProcessorDelay。



详见:http://tomcat.apache.org/tomcat-7.0-doc/config/engine.html。

实际上,org.apache.catalina.startup.HostConfig中存在如下方法:

addWatchedResources(DeployedApplication app, String docBase, Context context)

这个方法是tomcat在部署应用的时候调用的,它将应用的web.xml文件添加为监控对象。

后台线程通过检测该文件的时间戳是否发生变化,从而确定是否需要重新加载应用。

另外,需要特别注意:该特性需要配置Host元素的autoDeploy属性为true;若为false,即使应用web.xml文件发生变化,tomcat也不会重新加载应用。

<Host name="localhost"  appBase="webapps"
unpackWARs="true" autoDeploy="true">
</Host>

因为org.apache.catalina.startup.HostConfig在check时会判断autoDeploy是否为true。

/**
* Check status of all webapps.
*/
protected void check() { if (host.getAutoDeploy()) {
// Check for resources modification to trigger redeployment
DeployedApplication[] apps =
deployed.values().toArray(new DeployedApplication[0]);
for (int i = 0; i < apps.length; i++) {
if (!isServiced(apps[i].name))
checkResources(apps[i], false);
} // Check for old versions of applications that can now be undeployed
if (host.getUndeployOldVersions()) {
checkUndeploy();
} // Hotdeploy applications
deployApps();
}
}

【参考】

https://www.mulesoft.com/cn/tcat/tomcat-reload

tomcat自动重新加载应用的更多相关文章

  1. Tomcat是如何加载Spring和SpringMVC及Servlet相关知识

    概述 大家是否清楚,Tomcat是如何加载Spring和SpringMVC,今天我们就弄清下这个过程(记录最关键的东西) 其中会涉及到大大小小的知识,包括加载时候的设计模式,Servlet知识等,看了 ...

  2. ExtJs基础知识总结:自定义弹窗和ComboBox自动联想加载(四)

    概述 Extjs弹窗可以分为消息弹窗.对话框,这些弹窗的方式ExtJs自带的Ext.Msg.alert就已经可以满足简单消息提示,但是相对复杂的提示,比如如何将Ext.grid.Panel的控件显示嵌 ...

  3. Intellij如何设置编译后自动重新加载class文件?

    前段时间突然发现Intellij不能自动重新加载类了,每次编译后都要重新启动项目,才能显示更新效果,后来网上查询Intellij下如何配置热部署,都说是要配置构件,然后在web容器的编辑页面选择upd ...

  4. Tomcat的class加载的优先顺序

    Tomcat的class加载的优先顺序一览 1.最先是$JAVA_HOME/jre/lib/ext/下的jar文件. 2.环境变量CLASSPATH中的jar和class文件. 3.$CATALINA ...

  5. logstash 自动重新加载配置

    自动重新加载配置 为了可以自动检测配置文件的变动和自动重新加载配置文件,需要在启动的时候使用以下命令: ./bin/lagstash -f configfile.conf --config.reloa ...

  6. Fullcalendar改版后发布到IIS或者tomcat里面前端加载数据不显示的问题

    问题如题:Fullcalendar改版后发布到IIS或者tomcat里面前端加载数据不显示的问题 解决办法:通过火狐浏览器工具发现是时间格式不对的原因,需要将时间格式修改为:yyyy-MM--DD   ...

  7. Tomcat启动时加载数据到缓存---web.xml中listener加载顺序(优先初始化Spring IOC容器)

    JavaWebSpringTomcatCache  最近用到在Tomcat服务器启动时自动加载数据到缓存,这就需要创建一个自定义的缓存监听器并实现ServletContextListener接口,并且 ...

  8. Tomcat启动时加载数据到缓存---web.xml中listener加载顺序(例如顺序:1、初始化spring容器,2、初始化线程池,3、加载业务代码,将数据库中数据加载到内存中)

    最近公司要做功能迁移,原来的后台使用的Netty,现在要迁移到在uap上,也就是说所有后台的代码不能通过netty写的加载顺序加载了. 问题就来了,怎样让迁移到tomcat的代码按照原来的加载顺序进行 ...

  9. 前端自动生成/加载CSS

    前言: 1.我很懒! 2.写样式时,很多时候需要单独设置长度.宽度.内间距.外间距等.于是,就会有很多CSS代码会出现很多类似以下的代码: .w20: { width: 20px; } .mt10: ...

随机推荐

  1. BZOJ 5477: 星际穿越

    当初随便出的一道 思博题 竟然被交换到了八中 QAQ 然后就上了 BZOJ ...作为原作者还是把原来写的详细题解放出来吧 qwq 题意 \(n\) 个点的数,每个点初始有权值 \(v_i\) ,需要 ...

  2. Leetcode 350.两个数组的交集|| By Python

    给定两个数组,编写一个函数来计算它们的交集. 示例 1: 输入: nums1 = [1,2,2,1], nums2 = [2,2] 输出: [2,2] 示例 2: 输入: nums1 = [4,9,5 ...

  3. SAM练习记录

    SAM练习记录 洛谷 P1368 工艺 其实是最小表示法裸题 倍长后建SAM跑最小的边走|S|步即可 Code CF 235 C. Cyclical Quest 对主串建SAM 然后每个串倍长,跑的时 ...

  4. nginx.conf(centos6, 1.12)主配置文件修改

    #nginx1.12 centos6.xuser admin admin;worker_processes 4; error_log /data/services/logs/nginx_error.l ...

  5. Baker Vai LightOJ - 1071 (MCMF)

    在个给出的矩阵从,从左上角走到右下角,然后再从右下角走到左上角,两次不能经过想同的点,每个点都有一个价值,问最大的价值是多少. 可以把原来的问题化简成从左上角走两条路到右下角,然后把价值加起来,然是这 ...

  6. map映照容器

    //map映照容器是由一个键值和一个映照数据组成的,键值与映照数据之间具有一一映照的关系 //map映照容器的键值不允许重复 ,比较函数值对元素 //的键值进行比较,元素的各项数据可通过键值检索出来 ...

  7. Duplicate entry 'xxx' for key 'xxx'

    插入数据的时候 报错,Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplic ...

  8. bzoj3331 压力(圆方树)

    题目链接 圆方树 圆方树就是对于联通无向图中的每一个点双新建一个方点,与点双中的每个点连一条边,然后将原来的边删去.将原来的点看作圆点,新建的点看作方点.所以叫做圆方树. 性质 1.圆方树肯定是棵树( ...

  9. ImageMagick 笔记: 索引颜色(index color)、锁定图层,透明 png 转 gif (保持清晰度)

    今天在处理一张 png 透明背景的图片,大小: 16KB, 尺寸: 400 x 300,用到一段代码,也许对以后有用. /** 带透明背景和阴影的png图片, 转换成 gif, [索引色] + [锁住 ...

  10. Linux编译安装PHP参数说明

    php各参数配置详解 --prefix=/usr/local/php //指定 php 安装目录 --with-apxs2=/usr/local/apache/bin/apxs //整合apache, ...