Java使用WatchService監(jiān)控文件內(nèi)容變化的示例
場景
系統(tǒng)實現(xiàn)中經(jīng)常需要能夠感知配置文件的變化,然后及時更新上下文。
實現(xiàn)方案
- 自己起一個單獨線程,定時加載文件,實現(xiàn)較簡單,但是無法保證能夠?qū)崟r捕捉文件變化,同時耗CPU
- 使用commons-io中的 FileAlterationObserver,思想和上面類似,對比前后文件列表的變化,觸發(fā)對應(yīng)事件
- JDK 1.7提供的WatchService,利用底層文件系統(tǒng)提供的功能
使用 WatchService
WatchService用來監(jiān)控一個目錄是否發(fā)生改變,但是可以通過 WatchEvent 上下文定位具體文件的變化。具體使用過程中要注意以下兩點:
- 文件改變可能會觸發(fā)兩次事件(我的理解:文件內(nèi)容的變更,元數(shù)據(jù)的變更),可以通過文件的時間戳來控制
- 在文件變化事件發(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 + "----------------");
// 利用文件時間戳,防止觸發(fā)兩次
if (changed.endsWith(getLicenseName()) && lastModified != LAST_MOD && configFile.length > 0) {
logger.info("----------------- reloading -----------------");
LAST_MOD = lastModified; // 保存上一次時間戳
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
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
解讀springboot配置mybatis的sql執(zhí)行超時時間(mysql)
這篇文章主要介紹了解讀springboot配置mybatis的sql執(zhí)行超時時間(mysql),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-01-01
Maven分模塊開發(fā)與依賴管理和聚合和繼承及屬性深入詳細(xì)介紹
依賴管理是項目管理中非常重要的一環(huán)。幾乎任何項目開發(fā)的時候需要都需要使用到庫。而這些庫很可能又依賴別的庫,這樣整個項目的依賴形成了一個樹狀結(jié)構(gòu),而隨著這個依賴的樹的延伸和擴大,一系列問題就會隨之產(chǎn)生2022-10-10
java?常規(guī)輪詢長輪詢Long?polling實現(xiàn)示例詳解
這篇文章主要為大家介紹了java?常規(guī)輪詢長輪詢Long?polling實現(xiàn)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-12-12
Java語言基于無向有權(quán)圖實現(xiàn)克魯斯卡爾算法代碼示例
這篇文章主要介紹了Java語言基于無向有權(quán)圖實現(xiàn)克魯斯卡爾算法代碼示例,具有一定參考價值,需要的朋友可以了解下。2017-11-11
springboot 啟動時初始化數(shù)據(jù)庫的步驟
這篇文章主要介紹了springboot 啟動時初始化數(shù)據(jù)庫的步驟,幫助大家更好的理解和使用springboot框架,感興趣的朋友可以了解下2021-01-01
mapstruct的用法之qualifiedByName示例詳解
qualifiedByName的意思就是使用這個Mapper接口中的指定的默認(rèn)方法去處理這個屬性的轉(zhuǎn)換,而不是簡單的get?set,今天通過本文給大家介紹下mapstruct的用法之qualifiedByName示例詳解,感興趣的朋友一起看看吧2022-04-04

