Java FileSystemWatcher 不会捕获文件创建事件,直到所有文件都被写入,同时以高频率写入文件

Java FileSystemWatcher not catch file created event until all files be written while write file with high frequency

我正在尝试使用 Spring boot devtools filewatch 包的 FileSystemWatcher 在目录上监视文件创建事件 在写入文件时捕获创建的事件时工作正常。但是我在高频写入文件时遇到了问题。 FileSystemWatcher 将等待所有文件写入,然后为每个文件触发创建的事件。

所以,我希望 FileSystemWatcher 会在每个文件写入时触发创建的事件,而不是等到所有文件都写入后再触发事件。我怎样才能做到这一点。这是我的代码:

  1. 观看配置
@Configuration
public class FileWatchingConfiguration {

    private Logger logger = LoggerFactory.getLogger(FileWatchingConfiguration.class);

    @Value("${application.scope}")
    private String appScope;

    @Autowired
    DataFileChangeListener dataFileChangeListener;

    @Bean
    public FileSystemWatcher destDataWatcher(){

        String folderPath = appScope.equalsIgnoreCase("external") ? Utils.getSyncFolderPath(Constants.DIR_TYPE.EXT_DEST_DATA) : Utils.getSyncFolderPath(Constants.DIR_TYPE.INT_DEST_DATA);
        logger.info("Data Watcher folder path watching change " + folderPath );
        FileSystemWatcher fileSystemWatcher = new FileSystemWatcher(true, Duration.ofMillis(1000L), Duration.ofMillis(500L));
        fileSystemWatcher.addSourceDirectory(new File(folderPath));
        fileSystemWatcher.addListener(dataFileChangeListener);
        fileSystemWatcher.start();
        logger.info("dest Data fileSystemWatcher");
        return fileSystemWatcher;
    }

    @PreDestroy
    public void onDestroy() throws Exception {
        destDataWatcher().stop();
    }
}

这是我的 onchange 事件实现:

@Component
public class LogsFileChangeListener implements FileChangeListener {

    private Logger logger = LoggerFactory.getLogger(LogsFileChangeListener.class);

    @Autowired
    RabbitMQService rabbitMQService;

    @Value("${application.scope}")
    private String appScope;

    @Value("${residents.rabbitmq.listener.ext.sync.exchange}")
    private String extSyncExchange;

    @Value("${residents.rabbitmq.listener.int.sync.exchange}")
    private String intSyncExchange;

    @Value("${residents.rabbitmq.listener.file.create.routingKey}")
    private String routingKey;

    @Override
    public void onChange(Set<ChangedFiles> changeSet) {
        for(ChangedFiles cfiles : changeSet){
            for(ChangedFile cfile : cfiles){
                if(cfile.getType().equals(ChangedFile.Type.ADD) || cfile.getType().equals(ChangedFile.Type.MODIFY) && !isLocked(cfile.getFile().toPath())){
                    String fileName = cfile.getFile().getName();
                    logger.info("Operation: " + cfile.getType()
                            + " On Sync Data file: "+ fileName + " is done");

                    RabbitMessageModel rabbitMessageModelLog = new RabbitMessageModel();
                    rabbitMessageModel.setFileName(fileName);
                    rabbitMessageModel.setFolderPath(Utils.getSyncFolderPath(appScope.equalsIgnoreCase("external") ? Constants.DIR_TYPE.EXT_DEST_DATA : Constants.DIR_TYPE.INT_DEST_DATA));
                    rabbitMQService.send(rabbitMessageModelLog,routingKey, appScope.equalsIgnoreCase("external") ? extSyncExchange : intSyncExchange);

                }
            }
        }
    }

    private boolean isLocked(Path path) {
        try (FileChannel ch = FileChannel.open(path, StandardOpenOption.WRITE); FileLock lock = ch.tryLock()) {
            return lock == null;
        } catch (IOException e) {
            return true;
        }
    }
}

我找到了存储文件的文件夹被编写器进程锁定的根本原因。频率高的话,会一直锁到writer complete。因此,我将我的代码更改为另一种方式。我使用 common.io 包来监视文件夹,只锁定正在写入的文件而不是锁定文件夹。这样,我的编写器应用程序和侦听器应用程序就可以并行工作