springboot监听本地文件或监听文件上传事件动态更新redis缓存数据字典

1. 前戏

1. 数据字典文件模样

{
  "dict": [
    {
      "code": [
        {
          "text": "男1",
          "value": "01"
        },
        {
          "text": "女2",
          "value": "02"
        }
      ],
      "name": "性别",
      "key": "sex"
    },
    {
      "code": [
        {
          "text": "小学3",
          "value": "01"
        },
        {
          "text": "中学4",
          "value": "02"
        },
        {
          "text": "大学",
          "value": "03"
        }
      ],
      "name": "学校",
      "key": "school"
    },
	{
      "code": [
        {
          "text": "大1傻",
          "value": "01"
        },
        {
          "text": "二呆",
          "value": "02"
        }
      ],
      "name": "小名",
      "key": "smallName"
    }
  ]
}

2. pom

   <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-cache</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.6</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
    </dependencies>

1. 使用工具转成java类

存在问题? json
到最后展示的时候是不是有序的,讲师用的 LinkedHashMap百度可知他会保持有序

涉及持久化的要 implements Serializable
本次要存入redis 所以加上

@AllArgsConstructor
@NoArgsConstructor
@Data
public class Code implements Serializable {

    private String text;
    private String value;
}

@AllArgsConstructor
@NoArgsConstructor
@Data
public class Dict implements Serializable {

    private List<Code> code;
    private String name;
    private String key;
}
@Data
@AllArgsConstructor
@NoArgsConstructor
//@EqualsAndHashCode(callSuper = false)
public class Dictionary implements Serializable {
    private List<Dict> dict;
}

### 2. 监听本地文件
```java
package com.xujiang.xujiang.listen;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.monitor.FileAlterationListenerAdaptor;
import org.apache.commons.io.monitor.FileAlterationObserver;
import org.springframework.context.annotation.PropertySource;

import java.io.File;
import java.io.IOException;
import java.util.Arrays;

@Slf4j
@PropertySource("classpath:xu.properties")
public class FileListener extends FileAlterationListenerAdaptor {

    private ListenerService listenerService;

    public FileListener(ListenerService listenerService) {
        this.listenerService = listenerService;
    }
    public static final String KEY="dict";
//    @Autowired
//    XuProperties properties;
//    String key = "dict";

    @Override
    public void onFileCreate(File file) {
        log.info("FileListener 监听到文件新建,名称: {} 路径:{}", file.getName(), file.getAbsolutePath());
        try {
            listenerService.writeJsonFileToMemory(KEY, file);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onFileChange(File file) {
        log.info("FileListener 监听到文件改变,名称: {} 路径:{}", file.getName(), file.getAbsolutePath());
        try {
            listenerService.writeJsonFileToMemory(KEY, file);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onFileDelete(File file) {
        log.info("FileListener 监听到文件删除,名称: {} 路径:{}", file.getName(), file.getAbsolutePath());
        listenerService.clear(KEY);

        File folder = new File(file.getParent());
        String[] list = folder.list();


        if (list != null && list.length > 0) {
            Arrays.stream(list).filter((x) -> x.endsWith(".json")).forEach((y) -> {
                try {
                    listenerService.writeJsonFileToMemory(KEY, new File(file.getParent() + "\\"+y));
                    log.info("虽然被删除,但是同目录下我找到了这个:{}", y);

                } catch (IOException e) {
                    log.error("读文件错误, name: {}", y);
                }
            });

        }
    }


    @Override
    public void onStart(FileAlterationObserver observer) {
        log.info("FileListener 启动完毕,监听路径: {}", observer.getDirectory().getAbsolutePath());

    }
//
//    @Override
//    public void onDirectoryCreate(File directory) {
//        log.info("FileListener 监听到文件夹创建,名称: {}", directory.getName());
//
//    }
//
//    @Override
//    public void onDirectoryChange(File directory) {
//        log.info("FileListener 监听到文件夹修改,名称: {}", directory.getName());
//
//    }
//
//    @Override
//    public void onDirectoryDelete(File directory) {
//        log.info("FileListener 监听到文件夹删除,名称: {}", directory.getName());
//
//    }


}



package com.xujiang.xujiang.listen;

import com.xujiang.xujiang.XuProperties;
import org.apache.commons.io.filefilter.FileFilterUtils;
import org.apache.commons.io.filefilter.HiddenFileFilter;
import org.apache.commons.io.filefilter.IOFileFilter;
import org.apache.commons.io.monitor.FileAlterationMonitor;
import org.apache.commons.io.monitor.FileAlterationObserver;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Component;

import java.io.File;
import java.util.concurrent.TimeUnit;

@Component
@ConditionalOnProperty(value = "dict.option", havingValue = "auto")

public class FileListenerFactory {
    @Autowired
    XuProperties properties;
    // 设置监听路径
//    private final String monitorDir = "/tmp/monitorTest";

    // 设置轮询间隔
    private final long interval = TimeUnit.SECONDS.toMillis(1);

    // 自动注入业务服务
    @Autowired
    private ListenerService listenerService;

    public FileAlterationMonitor getMonitor() {
        // 创建过滤器
        IOFileFilter directories = FileFilterUtils.and(
                FileFilterUtils.directoryFileFilter(),
                HiddenFileFilter.VISIBLE);
        IOFileFilter files = FileFilterUtils.and(
                FileFilterUtils.fileFileFilter(),
                FileFilterUtils.suffixFileFilter(".json"));
        IOFileFilter filter = FileFilterUtils.or(directories, files);

        // 装配过滤器
        // FileAlterationObserver observer = new FileAlterationObserver(new File(monitorDir));
        FileAlterationObserver observer = new FileAlterationObserver(new File(properties.WATCH_DICT), filter);

        // 向监听者添加监听器,并注入业务服务
        observer.addListener(new FileListener(listenerService));

        // 返回监听者
        return new FileAlterationMonitor(interval, observer);
    }
}



package com.xujiang.xujiang.listen;

import org.apache.commons.io.monitor.FileAlterationMonitor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Component;

@Component
@ConditionalOnProperty(value = "dict.option", havingValue = "auto")

public class FileListenerRunner implements CommandLineRunner {

    @Autowired
    private FileListenerFactory fileListenerFactory;

    @Override
    public void run(String... args) throws Exception {
        // 创建监听者
        FileAlterationMonitor fileAlterationMonitor = fileListenerFactory.getMonitor();
        try {
            // do not stop this thread
            fileAlterationMonitor.start();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

太多了 不想复制了 …

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值