有过纯后台开发或者写过后台小工具的童鞋,肯定都遇到过这样的场景:
程序部署在测试环境或生产环境,这时候需要修改配置文件的一个参数,正常情况下,需要我们重启程序,有时候,参数调优,需要重启很多次,这就比较讨厌了...
最近无意中看到两篇博文,参考着他们,将这个小工具写好了。
两篇博文,单一的看,并不能满足需求。
http://blog.csdn.net/buptwds/article/details/44860625
这篇博文是监控目录下文件的状态。
http://blog.csdn.net/LoveJavaYDJ/article/details/73521726
这篇博文单纯的监控某个文件,并且要是src资源目录下的配置文件。
尝试过,修改博文中提供的代码,但感觉还是不行,于是想着将这两篇结合一下。
首先监控conf目录下所有的配置文件,有改动了,获取到该文件的文件名,然后直接重新读取就行。
举一个实际的栗子:
一个后台程序启动之后,配置类首先加载、读取conf目录下所有的配置文件,到内存中(第一次加载),这个配置类是单例的。
接着程序继续执行,调用监控配置文件方法(后台线程),然后完成初始化动作,然后运行一段时间后,修改配置文件参数,
当感知到配置文件修改之后,自动重新加载到内存中。
下面我们直接看代码:
package com.tools;
import java.io.File;
import java.io.FileInputStream;
import java.nio.file.FileSystems;
import java.nio.file.Paths;
import java.nio.file.StandardWatchEventKinds;
import java.nio.file.WatchEvent;
import java.nio.file.WatchKey;
import java.nio.file.WatchService;
import java.util.Properties;
/**
* 监控conf目录下文件是否改动
*
* http://blog.csdn.net/buptwds/article/details/44860625
* http://blog.csdn.net/LoveJavaYDJ/article/details/73521726
*
* 需求场景:程序启动;配置类单例,第一次加载配置文件;接着开始监控,如果配置文件修改,重新加载
*
* @author CYX
*
*/
public class WatchFile {
private static WatchService watchService;
private static Properties properties = new Properties();
private static String filePath;
public void watch() {
// conf目录全路径
filePath = (new File("conf").getAbsolutePath());
try {
// 获取文件系统的WatchService对象
watchService = FileSystems.getDefault().newWatchService();
// 监听'filePath'是否修改;register()方法后面监听事件种类还可以增加。
Paths.get(filePath).register(watchService, StandardWatchEventKinds.ENTRY_MODIFY);
} catch (Exception e) {
e.printStackTrace();
}
// 设置后台线程
Thread watchThread = new Thread(new Runnable() {
@Override
public void run() {
while (true) {
try {
// 获取下一个文件改动事件
WatchKey key = watchService.take();
for (WatchEvent<?> event : key.pollEvents()) {
System.out.println(filePath + "/" + event.context() + " --> " + event.kind());
System.out.println("重新加载 : " + filePath + "/" + event.context());
properties.load(new FileInputStream(new File(filePath + "/" + event.context())));
}
// 重设WatchKey
boolean valid = key.reset();
// 如果重设失败,退出监听
if (!valid) {
break;
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
});
// 设置为后台守护线程
watchThread.setDaemon(true);
watchThread.start();
}
/**
* 模拟测试
*
* @param args
* @throws Exception
*/
public static void main(String[] args) throws Exception {
// 程序启动;配置类第一次加载配置文件(配置类为单例)。
properties.load(new FileInputStream(new File("./conf/sysConfig2.properties")));
System.out.println("username1 : " + properties.get("username"));
System.out.println("age1 : " + properties.get("age"));
// 开启监听程序,如有改动,则更新对象
WatchFile w = new WatchFile();
w.watch();
// 假装做一些事情,延迟8秒。
Thread.sleep(8000);
// 延期之后,重新读取配置类中的参数。
System.out.println("username2 : " + properties.get("username"));
System.out.println("age2 : " + properties.get("age"));
}
}
代码就这些,就不上传Demo了...
测试结果:
项目结构