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)單,但是無(wú)法保證能夠?qū)崟r(shí)捕捉文件變化,同時(shí)耗CPU
- 使用commons-io中的 FileAlterationObserver,思想和上面類似,對(duì)比前后文件列表的變化,觸發(fā)對(duì)應(yīng)事件
- JDK 1.7提供的WatchService,利用底層文件系統(tǒng)提供的功能
使用 WatchService
WatchService用來(lái)監(jiān)控一個(gè)目錄是否發(fā)生改變,但是可以通過(guò) WatchEvent 上下文定位具體文件的變化。具體使用過(guò)程中要注意以下兩點(diǎn):
- 文件改變可能會(huì)觸發(fā)兩次事件(我的理解:文件內(nèi)容的變更,元數(shù)據(jù)的變更),可以通過(guò)文件的時(shí)間戳來(lái)控制
- 在文件變化事件發(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)文章
java中對(duì)象的強(qiáng)、軟、弱、虛四種引用詳解
這篇文章主要介紹了java中對(duì)象的強(qiáng)、軟、弱、虛四種引用詳解,對(duì)象的引用分為4種,分別是強(qiáng)引用>軟引用>弱引用>虛引用,程序員可以通過(guò)不同的引用控制對(duì)象的生命周期,方便垃圾回收,使程序更加靈活的控制對(duì)象生命周期,需要的朋友可以參考下2023-09-09SpringBoot?HikariCP配置項(xiàng)及源碼解析
這篇文章主要為大家介紹了SpringBoot?HikariCP配置項(xiàng)及源碼解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-02-02解析Mybatis的insert方法返回?cái)?shù)字-2147482646的解決
這篇文章主要介紹了解析Mybatis的insert方法返回?cái)?shù)字-2147482646的解決,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-04-04java實(shí)現(xiàn)屏幕共享功能實(shí)例分析
這篇文章主要介紹了java實(shí)現(xiàn)屏幕共享功能的方法,以實(shí)例形式分析了屏幕共享功能的客戶端與服務(wù)端的詳細(xì)實(shí)現(xiàn)方法,是非常具有實(shí)用價(jià)值的技巧,需要的朋友可以參考下2014-12-12java正則替換括號(hào)中的逗號(hào)實(shí)現(xiàn)示例
本文主要介紹了java正則替換括號(hào)中的逗號(hào)實(shí)現(xiàn)示例,主要介紹了兩種示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2024-01-01Spring Eureka 未授權(quán)訪問漏洞修復(fù)問題小結(jié)
項(xiàng)目組使用的 Spring Boot 比較老,是 1.5.4.RELEASE ,最近被檢測(cè)出 Spring Eureka 未授權(quán)訪問漏洞,這篇文章主要介紹了Spring Eureka 未授權(quán)訪問漏洞修復(fù)問題小結(jié),需要的朋友可以參考下2024-04-04