You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

运行时读取类路径下修改的TXT文件无法获取新数据问题

问题核心

本质是classpath资源的缓存机制导致的:

  • 开发环境中,Spring的ClassPathResource默认会缓存资源内容,即使修改外部源文件,读取的依然是缓存的旧数据。
  • 生产环境里,classpath文件打包在jar包内,修改jar外的源文件不会影响JVM已加载的资源,读取的始终是jar内的旧文件。
解决办法

1. 开发环境:绕开ClassPathResource缓存

直接读取项目源码目录下的实际文件,不依赖Spring缓存的Resource对象:

public void readFile() throws IOException {
    try {
        List<ClientValue> clients = new ArrayList<>();
        Path actualPath;
        // 判断是否为classpath资源
        if (filePath instanceof ClassPathResource) {
            // 直接指向src/main/resources下的真实文件路径
            String resourcePath = ((ClassPathResource) filePath).getPath();
            actualPath = Paths.get("src/main/resources", resourcePath);
        } else {
            actualPath = Paths.get(filePath.getURI());
        }
        // 后续读取逻辑不变
        Files.readAllLines(actualPath).stream()
                .skip(1)
                .map(line -> line.split(";"))
                .map(this::createClientValue)
                .forEach(clients::add);

        this.clients = clients;
        log.debug("Client values: {}", this.clients);
    } catch (IOException e) {
        log.error("无法读取clients.txt文件", e);
        throw new IllegalStateException();
    }
}

2. 生产环境:将文件移出classpath

生产环境不建议依赖classpath文件的动态更新,更可靠的方案是:

  • 将clients.txt放到应用外部固定目录,比如/opt/app/config/clients.txt
  • 修改配置文件中的filePath为外部路径,例如file:/opt/app/config/clients.txt
  • 代码直接读取该外部路径,彻底避开classpath缓存问题

3. 强制刷新Resource缓存(不推荐生产用)

如果必须使用classpath资源,每次读取时创建新的Resource实例并禁用缓存:

public void readFile() throws IOException {
    try {
        List<ClientValue> clients = new ArrayList<>();
        // 每次创建新的ClassPathResource实例,禁用缓存
        ClassPathResource freshResource = new ClassPathResource("clients.txt");
        freshResource.setUseCaches(false);
        Path actualPath = Paths.get(freshResource.getURI());
        
        Files.readAllLines(actualPath).stream()
                .skip(1)
                .map(line -> line.split(";"))
                .map(this::createClientValue)
                .forEach(clients::add);

        this.clients = clients;
        log.debug("Client values: {}", this.clients);
    } catch (IOException e) {
        log.error("无法读取clients.txt文件", e);
        throw new IllegalStateException();
    }
}
额外提醒
  • 确认FileChangeListener监听的是实际被修改的文件路径,而非classpath的缓存路径,否则触发监听也无法读取新内容。
  • 你实现的isLocked文件锁判断逻辑可以保留,能避免读取正在写入的不完整文件。

内容的提问来源于stack exchange,提问作者Dmitry-Dsafgi-Bachinin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 18:06:40