Springcloud学习笔记65---JNotify监听服务器文件变化(Java实现)

0 使用背景

我们在做数据接入或者文件解析的时候,经常需要对目录下的文件进行监控和解析。在对文件监控时,以前的做法是通过定时轮询该目录下,获取该目录的文件,该方法会有延时。JNotify给出java版的解决方案,引用Notify机制。

可以监听的文件信息包括

  • 文件夹/文件创建
  • 文件夹/文件删除
  • 文件夹/文件修改 (文件内容被修改和文件夹被修改都可以检测到)
  • 文件夹/文件重命名

1 导入maven依赖

    <dependency>
      <groupId>net.contentobjects.jnotify</groupId>
      <artifactId>jnotify</artifactId>
      <version>0.94</version>
    </dependency>

2 JNotify关键依赖

因为Jnotify底层调用的关键部分是C语言开发的,所以需要在系统中加入jnotify_64bit.dll(64位) (Windows)或者libjnotify.so(linux)动态库。

  • jnotify_64bit.dll(64位) 加入到System.getProperty(“java.library.path”)对应的路径
  • libjnotify.so加入到启动脚本的指定-Djava.library.path目录中

3 代码实现

JNotify.jar中的源码中JNotify_linux类中的静态方法System.loadLibrary("jnotify");

编写一个类继承JNotifyAdapter
重写方法
设置监听文件夹、添加需要监听的事件、是否监听子文件夹、 添加启动监视程序方法

package cn.itsqq.util;

import net.contentobjects.jnotify.JNotify;
import net.contentobjects.jnotify.JNotifyAdapter;
import net.contentobjects.jnotify.JNotifyException;

/**
 * ClassName: jnotify <br/>
 * Description: <br/>
 * date: 2020/6/10 10:21<br/>
 * @author shangqq<br />
 */
public class JnotifyTest extends JNotifyAdapter {


    //可以写到配置文件中
    private static final String REQUEST_BASE_PATH = "D:\\test";
    /**
     * 被监视的目录
     */
    String path = REQUEST_BASE_PATH;
    /**
     * 关注目录的事件 
     */
    int mask =JNotify.FILE_CREATED |JNotify.FILE_DELETED| JNotify.FILE_RENAMED| JNotify.FILE_MODIFIED;
    /**
     * 是否监视子目录,即级联监视
     */
    boolean watchSubtree = true;
    /**
     * 监听程序Id
     */
    public int watchID;

    /**
     * 容器启动时启动监视程序
     */
    public void beginWatch() {
        /**
         * 添加到监视队列中
         */
        try {
            this.watchID = JNotify.addWatch(path, mask, watchSubtree, this);
            System.err.println("jnotify -----------启动成功2-----------");
        } catch (JNotifyException e) {
            e.printStackTrace();
        }
        /**
         * 死循环,线程一直执行,休眠一分钟后继续执行,主要是为了让主线程一直执行 休眠时间和监测文件发生的效率无
         * (就是说不是监视目录文件改变一分钟后才监测到,监测几乎是实时的,调用本地系统库)
         */
        while (true) {
            try {
                //主要缓和主线程的执行效率,
                Thread.sleep(600);
            } catch (InterruptedException e) {// ignore it
            }
        }
    }

    /**
     * 文件创建
     * @param wd 监听程序Id 初始为1,多个监控程序以此加1
     * @param rootPath 目录名
     * @param name 文件名
     */

    @Override
    public void fileCreated(int wd, String rootPath, String name) {

        System.err.println(wd+"----->文件被创建, 创建位置为: " + rootPath + "\\" + name);
    }

    /**
     * 删除文件
     * @param wd 监听程序Id 初始为1,多个监控程序以此加1
     * @param rootPath 目录名
     * @param name 文件名
     */
    @Override
    public void fileDeleted(int wd, String rootPath, String name) {
        System.err.println(wd+"----->文件被删除, 被删除的文件名为:" + rootPath + name);
    }

    /**
     * 文件修改 (文件内容被修改和文件夹被修改都可以检测到)
     * @param wd 监听程序Id 初始为1,多个监控程序以此加1
     * @param rootPath 目录名
     * @param name 文件名
     */
    @Override
    public void fileModified(int wd, String rootPath, String name) {
        System.err.println(wd+"----->文件内容被修改, 文件名为:" + rootPath + "\\" + name);
    }

    /**
     * 文件重命名
     * @param wd 监听程序Id 初始为1,多个监控程序以此加1
     * @param rootPath 目录名
     * @param oldName 修改前目录名
     * @param newName 修改后目录名
     */
    @Override
    public void fileRenamed(int wd, String rootPath, String oldName, String newName) {
        System.err.println(wd+"----->文件被重命名, 原文件名为:" + rootPath + "\\" + oldName
                + ", 现文件名为:" + rootPath + "\\" + newName);
    }
}

主程序启动监听程序

package cn.itsqq.controller;
import cn.itsqq.util.Jnotify;
public class Main2 {
    public static void main(String[] args){
        //开一个线程,为了不影响主程序运行
         new Thread(){
             @Override
             public void run() {
                 JnotifyTest jnotifyTest = new JnotifyTest ();
                 jnotifyTest.beginWatch();
             }
         }.start();
    }
}

参考文献:

https://www.jianshu.com/p/34b38d050f72

posted @ 2024-05-09 15:26  雨后观山色  阅读(324)  评论(0编辑  收藏  举报