Springboot之文件监控
背景:在实际环境部署构成中,由于特殊网络环境因素,有很多服务器之间的网络都是单向的,不能互相访问的,只有通过特定技术手段做到文件的单项摆渡,这就需要在两台服务器上分别写序列化程序和反序列化程序,这里不记录序列化的内容,记录反序列化程序中的文件监控内容。
1、文件监控方式一:java的文件监控有两种方式,方法一:java7提供的 WatchService,但是这个方法有一些问题存在以下问题:
a.当文件修改的时候,会收到两次通知,这个问题需要通过自己写代码去解决
b.不能监控子目录下的文件变化
c.无法对监控文件进行过滤,只监控自己感兴趣的文件
2、文件监控方式二:commons-io(原理采用监控者模式和定时刷新监控文件夹),项目中实际使用的方式。
代码如下:
/** * 目录监听器 * * @return */ @Bean public FileAlterationMonitor fileAlterationMonitor(@Autowired DirectoryWatchService directoryWatchService, @Autowired FileFilter fileFilter) { //监控器 100 监控刷新时间 FileAlterationMonitor monitor = new FileAlterationMonitor(100);
// 多个文件夹监控,需要add多个观察者 for (String path : directoryPath) { log.info("监听目录:{}",path);
//对某个路径的观察者 FileAlterationObserver observer = new FileAlterationObserver(path, fileFilter); // 增加文件过滤,符合文件后缀的文件才进行处理,防止操作系统中生成的临时文件无法处理 //添加监听事件响应,与path无关,rsync同步需要 observer.addListener(directoryWatchService); //将观察者添加到监控器 monitor.addObserver(observer); } return monitor; }
目录监听服务
@Component @Slf4j public class DirectoryWatchService extends FileAlterationListenerAdaptor { @Override public void onStart(FileAlterationObserver observer) { log.debug("开始对目录:{}进行监听", observer.getDirectory().getPath()); } @Override public void onDirectoryCreate(File directory) { log.info("目录:{}创建", directory.getPath()); } @Override public void onDirectoryChange(File directory) { log.info("目录:{}改变", directory.getPath()); } @Override public void onDirectoryDelete(File directory) { log.info("目录:{}被删除", directory.getPath()); } @Override public void onFileCreate(File file) { log.info("文件:{}创建", file.getPath()); // TODO } @Override public void onFileChange(File file) { log.info("文件:{}改变", file.getPath()); } @Override public void onFileDelete(File file) { log.info("文件:{}删除", file.getPath()); } @Override public void onStop(FileAlterationObserver observer) { log.debug("停止目录{}监听", observer.getDirectory().getPath()); super.onStop(observer); } }
文件过滤器
public class BchtFileFilter implements FileFilter { @Override public boolean accept(File pathname) { if(pathname.getPath().endsWith(".data") || pathname.getPath().endsWith(".DATA")){ return true; } return false; } }