Java 实现日志文件监听并读取相关数据

Java 实现日志文件监听并读取相关数据

项目需求

由于所在数据中台项目组需要实现监听文件夹或者日志文件并读取对应格式的脏数据的需求,以便在文件、文件夹发生变化时进行相应的业务流程;所以在这里记录下相关业务的实现及技术选型。

Apache Commons-IO

首先需要添加对应依赖:

<dependency>
	<groupId>commons-io</groupId>
	<artifactId>commons-io</artifactId>
	<version>2.7</version>
</dependency>

版本可自行选择,这里需要注意的是 2.7 版本及以上需要 Java 8

官网截图:

Apache Commos IO中的 org.apache.commons.io.monitor包提供了文件系统监听的功能。

核心知识

  • 一句话总结:通过观察者模式以及事件监听机制,以 FileAlterationObserver 为核心,再通过 FileAlterationListenerFileAlterationMonitor,就可以实现对文件系统的事件监听。

  • 整体流程:

  1. 自定义文件监听类并继承 FileAlterationListenerAdaptor 实现对文件与目录的创建,修改,删除事件的处理
  2. 自定义文件监控类,通过指定目录创建一个观察者 FileAlterationObserver
  3. 向此监视器添加文件系统观察器,并添加文件监听器
  4. 通过 ApplicationRunner 或者 CommandLineRunner 调用并执行

代码实现

  • 文件监听类:
/**
 * 文件监听类
 * @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)){
                    // 获取对应格式的数据并输出,这里可自行添加业务处理
                    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("读取文件内容失败",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");
    }
}
  • 文件监控类:
/**
 * 文件监听测试 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);
    }

    /**
     * 给文件添加监听
     * @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 并实现 CommandLineRunner :
/**
 * 项目启动之后开启文件监听功能
 * @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()+"[开启文件夹监听功能]");
        FileMonitor fileMonitor = new FileMonitor(1000);
        fileMonitor.monitor(path,new FileListener());
        fileMonitor.start();
    }
}

总结

  • 文件、文件夹监听功能较简单,实现方式可自行选择
  • 需要注意的是,通过 Runner 的方式在项目启动之后开启相关监听功能,此方式存在缺陷,只能调用一次,出现异常就会停止,除非项目重启,这里需要通过相关补偿机制来实现
  • 1
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
读取 MySQL 的增删改日志文件,可以使用 MySQL 的 binlog,binlog 是 MySQL 的二进制日志,记录了 MySQL 的所有更新操作,包括增删改等。 下面是使用 Spring Boot 读取 MySQL binlog 的步骤: 1. 在 MySQL 配置文件中开启 binlog,可以在 my.cnf 或 my.ini 文件中添加如下配置: ``` [mysqld] log-bin=mysql-bin binlog-format=ROW ``` 这里将 binlog 日志文件存储在名为 mysql-bin 的文件中,格式为 ROW。 2. 在 Spring Boot 中添加 MySQL 驱动和 binlog 相关的依赖,例如: ``` <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.23</version> </dependency> <dependency> <groupId>com.github.shyiko</groupId> <artifactId>mysql-binlog-connector-java</artifactId> <version>0.17.0</version> </dependency> ``` 这里使用了 mysql-connector-java 和 mysql-binlog-connector-java 两个依赖。 3. 在 Spring Boot 中编写读取 binlog 日志的代码,例如: ``` @Component public class BinlogReader { private final BinaryLogClient client; public BinlogReader() { client = new BinaryLogClient("localhost", 3306, "root", "password"); client.registerEventListener(event -> { EventData data = event.getData(); if (data instanceof WriteRowsEventData) { WriteRowsEventData write = (WriteRowsEventData) data; System.out.println("inserted rows: " + write.getRows()); } else if (data instanceof UpdateRowsEventData) { UpdateRowsEventData update = (UpdateRowsEventData) data; System.out.println("updated rows: " + update.getRows()); } else if (data instanceof DeleteRowsEventData) { DeleteRowsEventData delete = (DeleteRowsEventData) data; System.out.println("deleted rows: " + delete.getRows()); } }); } @PostConstruct public void start() throws IOException { client.connect(); } @PreDestroy public void stop() throws IOException { client.disconnect(); } } ``` 这里使用了 BinaryLogClient 类来连接 MySQL,通过 registerEventListener 方法注册事件监听器来监听 binlog 日志的写入、更新、删除操作。 需要注意的是,直接读取 MySQL 的 binlog 日志文件可能会对性能和稳定性造成影响,建议在使用前先进行充分测试和评估。同时,也建议使用专业的数据库同步工具来进行 MySQL 数据库的同步,如阿里云的 DTS、腾讯云的 CDC 等。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值