首先我们在项目中总会使用到一些properties或者xml文件,那么正常情况下当我们修改这些文件的时候,我们需要重启服务器让系统的类重新去加载这些文件。这样就会导致改动一点点就需要重启服务器,很不方便。
解决的办法:利用监听器来监听到文件的改变,然后让程序重新加载文件,这样就达到类似热更新的效果.
在此说明,我以下所写内容,大部分都是参考了一篇博客,在此非常谢谢这位博主。
博客:https://blog.csdn.net/u013223806/article/details/85858494
好了 正文开始。
一、引入jar包
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.4</version>
</dependency>
二、实现FileAlterationListenerAdaptor 这个类,然后根据需要重写里面方法,比如onFileChange:文件修改之后需要做什么,onStart:监听启动的时候需要做什么,等等
我自己这里只是简单的实现了当文件被修改的时候,我需要做什么。
2.1 新建MyFileListenerAdaptor 继承 FileAlterationListenerAdaptor
2.2 创建自定义文件监视器类MyFileAlterationMonitor,可用来实现热更配置文件/监听文件场景。(由于太长,或者去上面的博客里面看,一样的)
package top.aiprogram.common;
import org.apache.commons.io.filefilter.FileFilterUtils;
import org.apache.commons.io.monitor.FileAlterationListenerAdaptor;
import org.apache.commons.io.monitor.FileAlterationMonitor;
import org.apache.commons.io.monitor.FileAlterationObserver;
public class MyFileAlterationMonitor{
/***
* 自定义文件监视器,可用来实现热更配置文件/监听文件场景
* @author Zane
* @Time 2019年1月5日 上午10:41:12
*/
private Stringpath; // 文件夹目录
private StringfileSuffix; // 需要监听的文件名后缀
private long interval; // 监听间隔
private static final long DEFAULT_INTERVAL =10 *1000; // 默认监听间隔10s
private FileAlterationListenerAdaptorlistener; // 事件处理类对象
public MyFileAlterationMonitor(){
this.interval =DEFAULT_INTERVAL;
}
public MyFileAlterationMonitor(String path, String fileSuffix, FileAlterationListenerAdaptor listenerAdaptor){
this.path = path;
this.fileSuffix = fileSuffix;
this.interval =DEFAULT_INTERVAL;
this.listener = listenerAdaptor;
}
public MyFileAlterationMonitor(String path, String fileSuffix, long interval, FileAlterationListenerAdaptor listenerAdaptor) {
this.path = path;
this.fileSuffix = fileSuffix;
this.interval = interval;
this.listener = listenerAdaptor;
}
/***
* 开启监听
*/
public void start() {
if(path==null) {
throw new IllegalStateException("Listen path must not be null");
}
if(listener==null) {
throw new IllegalStateException("Listener must not be null");
}
// 设定观察者,监听.properties文件
FileAlterationObserver observer =new FileAlterationObserver(path,
FileFilterUtils.suffixFileFilter(fileSuffix));
// 给观察者添加监听事件
observer.addListener(listener);
// 开启一个监视器,监听频率是5s一次
// FileAlterationMonitor本身实现了 Runnable,是单独的一个线程,按照设定的时间间隔运行,默认间隔是10s
FileAlterationMonitor monitor =new FileAlterationMonitor(interval);
monitor.addObserver(observer);
try {
monitor.start();
} catch (Exception e) {
e.printStackTrace();
}
}
public void setPath(String path) {
this.path = path;
}
public void setFileSuffix(String fileSuffix) {
this.fileSuffix = fileSuffix;
}
public void setAdaptor(FileAlterationListenerAdaptor listenerAdaptor) {
this.listener = listenerAdaptor;
}
}
3.3 弄好这2个类文件开始测试.
main 方法里面直接测试,我这里用的文件目录是db.properties所在的文件目录.检测.properties的文件.
让它跑起来,它会一直处于监听状态。为什么会一直处于监听状态呢,因为monitor这个对象其实是实现了Runnable接口,所以是一个线程来的。
然后等他跑起来,我们修改一下properties文件,就会出发文件修改的效果,如下图。
三、具体项目启动如何也把它启动呢
按照上面,我们只是在main方法玩玩,对项目好像没什么用处。当tomcat启动时候,我们也想让它启动。我自己用的方法就是,创建一个监听器去监听ServletContext(web容器),然后在初始化方法中去启动这个监听就能简单的实现了监听文件的变化了。如下图:
我创建MyListener实现ServletContextListener,别忘记了在web.xml把这个监听器配置上。或者直接在这个类上打上注解@WebListener()就不用在web.xml配置
最后,我这里只是简单的实现监听文件的修改,并作出相对反应,监听文件修改后触发的动作具体还是要看项目上的业务。
对于为什么能监听到文件的变化,我自己思考想了一下,应该是文件会有一个最后修改时间,然后所以可以根据这个就知道文件有没修改。