Java實(shí)現(xiàn)日志文件監(jiān)聽并讀取相關(guān)數(shù)據(jù)的方法實(shí)踐
項(xiàng)目需求
由于所在數(shù)據(jù)中臺(tái)項(xiàng)目組需要實(shí)現(xiàn)監(jiān)聽文件夾或者日志文件并讀取對(duì)應(yīng)格式的臟數(shù)據(jù)的需求,以便在文件、文件夾發(fā)生變化時(shí)進(jìn)行相應(yīng)的業(yè)務(wù)流程;所以在這里記錄下相關(guān)業(yè)務(wù)的實(shí)現(xiàn)及技術(shù)選型。
Apache Commons-IO
首先需要添加對(duì)應(yīng)依賴:
<dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.7</version> </dependency>
版本可自行選擇,這里需要注意的是 2.7 版本及以上需要 Java 8
官網(wǎng)截圖:
Apache Commos IO中的 org.apache.commons.io.monitor
包提供了文件系統(tǒng)監(jiān)聽的功能。
核心知識(shí)
- 一句話總結(jié):通過觀察者模式以及事件監(jiān)聽機(jī)制,以
FileAlterationObserver
為核心,再通過FileAlterationListener
,FileAlterationMonitor
,就可以實(shí)現(xiàn)對(duì)文件系統(tǒng)的事件監(jiān)聽。 - 整體流程:
- 自定義文件監(jiān)聽類并繼承
FileAlterationListenerAdaptor
實(shí)現(xiàn)對(duì)文件與目錄的創(chuàng)建,修改,刪除事件的處理 - 自定義文件監(jiān)控類,通過指定目錄創(chuàng)建一個(gè)觀察者
FileAlterationObserver
- 向此監(jiān)視器添加文件系統(tǒng)觀察器,并添加文件監(jiān)聽器
- 通過
ApplicationRunner
或者CommandLineRunner
調(diào)用并執(zhí)行
代碼實(shí)現(xiàn)
- 文件監(jiān)聽類:
/** * 文件監(jiān)聽類 * @author Greenarrow * @date 2022-05-12 14:43 **/ public class FileListener extends FileAlterationListenerAdaptor { private static Logger logger = LoggerFactory.getLogger(FileListener.class); @Override public void onStart(FileAlterationObserver observer) { super.onStart(observer); logger.info("onStart"); } @Override public void onDirectoryCreate(File directory) { logger.info("[新建]:" + directory.getAbsolutePath()); } @Override public void onDirectoryChange(File directory) { logger.info("[修改]:" + directory.getAbsolutePath()); } @Override public void onDirectoryDelete(File directory) { logger.info("[刪除]:" + directory.getAbsolutePath()); } @Override public void onFileCreate(File file) { String compressedPath = file.getAbsolutePath(); logger.info("[新建]:" + compressedPath); List<String> contentList = null; try { if (file.canRead()){ // 將文件按行讀取為字符串集合 contentList = FileUtils.readLines(new File(compressedPath), StandardCharsets.UTF_8); if (CollectionUtil.isNotEmpty(contentList)){ // 獲取對(duì)應(yīng)格式的數(shù)據(jù)并輸出,這里可自行添加業(yè)務(wù)處理 List<String> dirtyRecord = contentList.stream().filter(s -> s.startsWith("{") && s.endsWith("}")).collect(Collectors.toList()); dirtyRecord.forEach(System.out::println); } } } catch (IOException e) { e.printStackTrace(); logger.error("讀取文件內(nèi)容失敗",e); } } @Override public void onFileChange(File file) { String compressedPath = file.getAbsolutePath(); logger.info("[修改]:" + compressedPath); } @Override public void onFileDelete(File file) { logger.info("[刪除]:" + file.getAbsolutePath()); } @Override public void onStop(FileAlterationObserver observer) { super.onStop(observer); logger.info("onStop"); } }
- 文件監(jiān)控類:
/** * 文件監(jiān)聽測試 demo * @author Greenarrow * @date 2022-05-12 14:45 **/ public class FileMonitor { FileAlterationMonitor monitor = null; public FileMonitor(long interval) throws Exception { monitor = new FileAlterationMonitor(interval); } /** * 給文件添加監(jiān)聽 * @param path * @param listener */ public void monitor(String path, FileAlterationListener listener) { FileAlterationObserver observer = new FileAlterationObserver(new File(path)); monitor.addObserver(observer); observer.addListener(listener); } public void stop() throws Exception { monitor.stop(); } public void start() throws Exception { monitor.start(); } }
- 自定義 Runner 并實(shí)現(xiàn)
CommandLineRunner
:
/** * 項(xiàng)目啟動(dòng)之后開啟文件監(jiān)聽功能 * @author Greenarrow * @date 2022-05-12 10:02 **/ @Component // @Order(Integer.MIN_VALUE) public class DirtyRecordRunner implements CommandLineRunner { private static Logger logger = LoggerFactory.getLogger(DirtyRecordRunner.class); @Value("${test}") private String path; @Override public void run(String... args) throws Exception { logger.info(this.getClass().getName()+"[開啟文件夾監(jiān)聽功能]"); FileMonitor fileMonitor = new FileMonitor(1000); fileMonitor.monitor(path,new FileListener()); fileMonitor.start(); } }
總結(jié)
文件、文件夾監(jiān)聽功能較簡單,實(shí)現(xiàn)方式可自行選擇
需要注意的是,通過 Runner 的方式在項(xiàng)目啟動(dòng)之后開啟相關(guān)監(jiān)聽功能,此方式存在缺陷,只能調(diào)用一次,出現(xiàn)異常就會(huì)停止,除非項(xiàng)目重啟,這里需要通過相關(guān)補(bǔ)償機(jī)制來實(shí)現(xiàn)
到此這篇關(guān)于Java實(shí)現(xiàn)日志文件監(jiān)聽并讀取相關(guān)數(shù)據(jù)的方法實(shí)踐的文章就介紹到這了,更多相關(guān)Java 日志文件監(jiān)聽讀取內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
解析Mybatis的insert方法返回?cái)?shù)字-2147482646的解決
這篇文章主要介紹了解析Mybatis的insert方法返回?cái)?shù)字-2147482646的解決,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-04-04Springboot實(shí)現(xiàn)多線程注入bean的工具類操作
這篇文章主要介紹了Springboot實(shí)現(xiàn)多線程注入bean的工具類操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-08-08Java語言實(shí)現(xiàn)非遞歸實(shí)現(xiàn)樹的前中后序遍歷總結(jié)
今天小編就為大家分享一篇關(guān)于Java語言實(shí)現(xiàn)非遞歸實(shí)現(xiàn)樹的前中后序遍歷總結(jié),小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧2019-01-01Java陷阱之a(chǎn)ssert關(guān)鍵字詳解
這篇文章詳細(xì)介紹了Java陷阱之a(chǎn)ssert關(guān)鍵字,有需要的朋友可以參考一下2013-09-09