Java Review - 使用Event Bus实现目录变化的监控

Posted 小小工匠

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java Review - 使用Event Bus实现目录变化的监控相关的知识,希望对你有一定的参考价值。


Pre

Java Review - Java进程内部的消息中间件_Event Bus设计模式


需求

监控文件的实时变化 , 就这一句话???

分析一下其中一个有问题的思路:

程序首次启动时获取该文件的最后修改时间并且做文件的首次解析,然后每隔一段指定的时间检查一次文件最后被修改的时间,如果与记录的时间相等则等待下次的采集(Balking Pattern),否则进行新一轮的采集并且更新时间。

这。。。。有问题啊 , 比如在采集时间间隔内,文件发生了N次变化,只能获取到最后一次,其根本原因是文件的变化不会通知到应用程序, 我只能傻傻的轮询~

新思路:

JDK自1.7版本后提供了WatchService类,该类可以基于事件通知的方式监控文件或者目录的任何变化,文件的改变相当于每一个事件(Event)的发生,针对不同的时间执行不同的动作,结合NIO2.0中提供的WatchService和Event Bus实现文件目录的监控的功能。


Event Bus案例实战


import com.artisan.bfzm.eventbus.EventBus;

import java.nio.file.*;

/**
 * @author 小工匠
 * @version 1.0
 * @description: TODO
 * @date 2021/12/2 16:37
 * @mark: show me the code , change the world
 */
public class DirectoryTargetMonitor 

    private WatchService watchService;

    private final EventBus eventBus;

    private final Path path;

    private volatile boolean start = false;

    public DirectoryTargetMonitor(final EventBus eventBus,
                                  final String targetPath) 
        this(eventBus, targetPath, "");
    

    /**
     *
     * 构造Monitor的时候需要传入EventBus以及需要监控的目录
     * @param eventBus
     * @param targetPath
     * @param morePaths
     */
    public DirectoryTargetMonitor(final EventBus eventBus,
                                  final String targetPath, final String... morePaths) 
        this.eventBus = eventBus;
        this.path = Paths.get(targetPath, morePaths);
    

    public void startMonitor() throws Exception 
        this.watchService = FileSystems.getDefault().newWatchService();
        //为路径注册感兴趣的事件
        this.path.register(watchService,
                StandardWatchEventKinds.ENTRY_MODIFY,
                StandardWatchEventKinds.ENTRY_DELETE,
                StandardWatchEventKinds.ENTRY_CREATE);
        System.out.printf("The directory [%s] is monitoring... \\n", path);
        this.start = true;
        while (start) 
            WatchKey watchKey = null;
            try 
                //当有事件发生时会返回对应的WatchKey
                watchKey = watchService.take();
                watchKey.pollEvents().forEach(event ->
                
                    WatchEvent.Kind<?> kind = event.kind();
                    Path path = (Path) event.context();
                    Path child = DirectoryTargetMonitor.this.path.resolve(path);
                    //提交FileChangeEvent到EventBus
                    eventBus.post(new FileChangeEvent(child, kind));
                );
             catch (Exception e) 
                this.start = false;
             finally 
                if (watchKey != null) 
                    watchKey.reset();
                
            
        
    

    public void stopMonitor() throws Exception 
        System.out.printf("The directory [%s] monitor will be stop...\\n", path);
        Thread.currentThread().interrupt();
        this.start = false;
        this.watchService.close();
        System.out.printf("The directory [%s] monitor will be stop done.\\n", path);
    

    

在创建WatchService之后将文件的修改、删除、创建等注册给了WatchService,在指定目录下发生诸如此类的事件之后便会收到通知,我们将事件类型和发生变化的文件Path封装成FileChangeEvent提交给Event Bus

以上是关于Java Review - 使用Event Bus实现目录变化的监控的主要内容,如果未能解决你的问题,请参考以下文章

Java Review - Java进程内部的消息中间件_Event Bus设计模式

Orchard源码分析(4.3):Orchard.Events.EventsModule类(Event Bus)

Flutter eventBus

EventBus - Android's Event Bus

EventBus系列:Event Bus 3.0中索引Subscriber Index使用指南

Android_Event Bus 的基本用法