Java实现文件变化监听
一、前言
1、简介
在平时的开发过程中,会有很多场景需要实时监听文件的变化,如下:
- 通过实时监控 mysql 的 binlog 日志实现数据同步
- 修改配置文件后,希望系统可以实时感知
- 应用系统将日志写入文件中,日志监控系统可以实时抓取日志,分析日志内容并进行报警
- 类似 ide 工具,可以实时感知管理的工程下的文件变更
2、三种方法介绍
-
定时任务 + File#lastModified
-
WatchService
-
Apache Commons-IO
二、三种方法实现
1、定时任务 + File#lastModified
通过定时任务,轮训查询文件的最后修改时间,与上一次进行对比。如果发生变化,则说明文件已经修改,进行重新加载或对应的业务逻辑处理
对于文件低频变动的场景,这种方案实现简单,基本上可以满足需求。但该方案如果用在文件目录的变化上,缺点就有些明显了,比如:操作频繁,效率都损耗在遍历、保存状态、对比状态上了,无法充分利用OS的功能。
1 | public class FileWatchDemo { |
同时该方案存在Bug:在Java8和9的某些版本下,lastModified方法返回时间戳并不是毫秒,而是秒,也就是说返回结果的后三位始终为0
2、WatchService
2.1 介绍
在Java 7中新增了
java.nio.file.WatchService
,通过它可以实现文件变动的监听。WatchService是基于操作系统的文件系统监控器,可以监控系统所有文件的变化,无需遍历、无需比较,是一种基于信号收发的监控,效率高
相对于方案一,实现起来简单,效率高。不足的地方也很明显,只能监听当前目录下的文件和目录,不能监视子目录。另外对于jdk8之后版本来说,该方案已经实现实时监听,不存在准实时的问题
2.2 简单示例
1 | public class WatchServiceDemo { |
2.3 完整示例
创建FileWatchedListener
接口
1 | public interface FileWatchedListener { |
创建FileWatchedAdapter
实现类,实现文件监听的方法
1 | public class FileWatchedAdapter implements FileWatchedListener { |
创建FileWatchedService
监听类,监听文件
1 | public class FileWatchedService { |
3、Apache Commons-IO
3.1 介绍与环境准备
commons-io
对实现文件监听的实现位于org.apache.commons.io.monitor
包下,基本使用流程如下:
-
自定义文件监听类并继承
FileAlterationListenerAdaptor
实现对文件与目录的创建、修改、删除事件的处理; -
自定义文件监控类,通过指定目录创建一个观察者
FileAlterationObserver
; -
向监视器添加文件系统观察器,并添加文件监听器;
-
调用并执行。
1 | <!--注意,不同的版本需要不同的JDK支持,2.7需要Java 8及以上版本--> |
3.2 原理讲解
该方案中监听器本身会启动一个线程定时处理。在每次运行时,都会先调用事件监听处理类的onStart方法,然后检查是否有变动,并调用对应事件的方法;比如,onChange文件内容改变,检查完后,再调用onStop方法,释放当前线程占用的CPU资源,等待下次间隔时间到了被再次唤醒运行。
监听器是基于文件目录为根源的,也可以可以设置过滤器,来实现对应文件变动的监听。过滤器的设置可查看FileAlterationObserver
的构造方法:
1 | public FileAlterationObserver(String directoryName, FileFilter fileFilter, IOCase caseSensitivity) { |
3.2 实战演示
创建文件监听器。根据需要在不同的方法内实现对应的业务逻辑处理
1 | public class FileListener extends FileAlterationListenerAdaptor { |
封装一个文件监控的工具类,核心就是创建一个观察者FileAlterationObserver
,将文件路径Path和监听器FileAlterationListener
进行封装,然后交给FileAlterationMonitor
1 | public class FileMonitor { |
调用执行
1 | public class FileRunner { |
参考文章
https://segmentfault.com/a/1190000041913336