Java使用WatchService監(jiān)控文件內(nèi)容變化的示例
場(chǎng)景
系統(tǒng)實(shí)現(xiàn)中經(jīng)常需要能夠感知配置文件的變化,然后及時(shí)更新上下文。
實(shí)現(xiàn)方案
- 自己起一個(gè)單獨(dú)線程,定時(shí)加載文件,實(shí)現(xiàn)較簡(jiǎn)單,但是無法保證能夠?qū)崟r(shí)捕捉文件變化,同時(shí)耗CPU
- 使用commons-io中的 FileAlterationObserver,思想和上面類似,對(duì)比前后文件列表的變化,觸發(fā)對(duì)應(yīng)事件
- JDK 1.7提供的WatchService,利用底層文件系統(tǒng)提供的功能
使用 WatchService
WatchService用來監(jiān)控一個(gè)目錄是否發(fā)生改變,但是可以通過 WatchEvent 上下文定位具體文件的變化。具體使用過程中要注意以下兩點(diǎn):
- 文件改變可能會(huì)觸發(fā)兩次事件(我的理解:文件內(nèi)容的變更,元數(shù)據(jù)的變更),可以通過文件的時(shí)間戳來控制
- 在文件變化事件發(fā)生后,如果立即讀取文件,可能所獲內(nèi)容并不完整,建議的做法判斷文件的 length > 0
// 監(jiān)控文件的變化,重新加載
executor.submit(new Runnable() {
@Override
public void run() {
try {
final Path path = FileSystems.getDefault().getPath(getMonitorDir());
System.out.println(path);
final WatchService watchService = FileSystems.getDefault().newWatchService();
final WatchKey watchKey = path.register(watchService, StandardWatchEventKinds.ENTRY_MODIFY);
while (true) {
final WatchKey wk = watchService.take();
for (WatchEvent<?> event : wk.pollEvents()) {
final Path changed = (Path) event.context();
Path absolute = path.resolve(changed);
File configFile = absolute.toFile();
long lastModified = configFile.lastModified();
logger.info(lastModified + "----------------");
// 利用文件時(shí)間戳,防止觸發(fā)兩次
if (changed.endsWith(getLicenseName()) && lastModified != LAST_MOD && configFile.length > 0) {
logger.info("----------------- reloading -----------------");
LAST_MOD = lastModified; // 保存上一次時(shí)間戳
UPDATED = true; // 設(shè)置標(biāo)志位
}
}
if (UPDATED) {
reloadFile(); // 重新加載
}
// reset the key
boolean valid = wk.reset();
if (!valid) {
logger.error("watch key invalid!");
}
}
} catch (Exception e) {
logger.error("");
}
}
});
參考
Watching a Directory for Changes
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- 基于spring-boot和docker-java實(shí)現(xiàn)對(duì)docker容器的動(dòng)態(tài)管理和監(jiān)控功能[附完整源碼下載]
- Java實(shí)現(xiàn)實(shí)時(shí)監(jiān)控目錄下文件變化的方法
- Java實(shí)時(shí)監(jiān)控日志文件并輸出的方法詳解
- java獲取redis日志信息與動(dòng)態(tài)監(jiān)控信息的方法
- java實(shí)現(xiàn)文件變化監(jiān)控的方法(推薦)
- SHELL腳本監(jiān)控JAVA進(jìn)程的代碼
- 使用Java編寫一個(gè)簡(jiǎn)單的Web的監(jiān)控系統(tǒng)
- Java服務(wù)器主機(jī)信息監(jiān)控工具類的示例代碼
相關(guān)文章
解讀springboot配置mybatis的sql執(zhí)行超時(shí)時(shí)間(mysql)
這篇文章主要介紹了解讀springboot配置mybatis的sql執(zhí)行超時(shí)時(shí)間(mysql),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-01-01
Maven分模塊開發(fā)與依賴管理和聚合和繼承及屬性深入詳細(xì)介紹
依賴管理是項(xiàng)目管理中非常重要的一環(huán)。幾乎任何項(xiàng)目開發(fā)的時(shí)候需要都需要使用到庫(kù)。而這些庫(kù)很可能又依賴別的庫(kù),這樣整個(gè)項(xiàng)目的依賴形成了一個(gè)樹狀結(jié)構(gòu),而隨著這個(gè)依賴的樹的延伸和擴(kuò)大,一系列問題就會(huì)隨之產(chǎn)生2022-10-10
java?常規(guī)輪詢長(zhǎng)輪詢Long?polling實(shí)現(xiàn)示例詳解
這篇文章主要為大家介紹了java?常規(guī)輪詢長(zhǎng)輪詢Long?polling實(shí)現(xiàn)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-12-12
Java語言基于無向有權(quán)圖實(shí)現(xiàn)克魯斯卡爾算法代碼示例
這篇文章主要介紹了Java語言基于無向有權(quán)圖實(shí)現(xiàn)克魯斯卡爾算法代碼示例,具有一定參考價(jià)值,需要的朋友可以了解下。2017-11-11
springboot 啟動(dòng)時(shí)初始化數(shù)據(jù)庫(kù)的步驟
這篇文章主要介紹了springboot 啟動(dòng)時(shí)初始化數(shù)據(jù)庫(kù)的步驟,幫助大家更好的理解和使用springboot框架,感興趣的朋友可以了解下2021-01-01
mapstruct的用法之qualifiedByName示例詳解
qualifiedByName的意思就是使用這個(gè)Mapper接口中的指定的默認(rèn)方法去處理這個(gè)屬性的轉(zhuǎn)換,而不是簡(jiǎn)單的get?set,今天通過本文給大家介紹下mapstruct的用法之qualifiedByName示例詳解,感興趣的朋友一起看看吧2022-04-04

