【问题标题】:Java FileSystemWatcher not catch file created event until all files be written while write file with high frequencyJava FileSystemWatcher 在高频写入文件时不会捕获文件创建事件,直到所有文件都被写入
【发布时间】:2020-12-10 04:09:11
【问题描述】:

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

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

  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;
        }
    }
}

【问题讨论】:

    标签: java spring file rabbitmq devtools


    【解决方案1】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-08-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-09-25
      • 1970-01-01
      相关资源
      最近更新 更多