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

Spring Boot项目Jar运行时如何遍历resources下的rules文件夹执行SQL

解决方案

问题根因

Spring Boot 打包为jar包后,内部资源以嵌套形式存储在jar归档文件中,不属于操作系统文件系统的普通文件/目录,因此无法通过java.io.File API直接读取、遍历,这就是IDE运行正常、jar运行失败的核心原因。

实现方案

采用Spring内置的ResourcePatternResolver实现classpath资源的递归扫描,通过流的方式读取文件内容,兼容IDE和jar两种运行环境。

修改后的代码实现

import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;

private static final String RULES_SCAN_PATH = "classpath*:/rules/**/*";
private static final String INSERT_SUFFIX = ".insert";
private static final String TAB = "\t";

private void loadDb() {
    log.info("Hello!");
    ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
    try {
        // 递归扫描rules目录下所有资源
        Resource[] resources = resolver.getResources(RULES_SCAN_PATH);
        log.info("**********************************************");
        log.info("Total resources found under rules directory: {}", resources.length);
        log.info("**********************************************");

        for (Resource resource : resources) {
            if (!resource.isReadable()) continue;
            String fullPath = resource.getURI().toString();
            // 只处理后缀为.insert的SQL文件
            if (!fullPath.endsWith(INSERT_SUFFIX)) continue;

            // 提取相对路径计算层级,实现缩进展示
            String relativePath = fullPath.substring(fullPath.indexOf("/rules/") + 7);
            int level = (int) relativePath.chars().filter(c -> c == '/').count();
            for (int i = 0; i < level; i++) {
                System.out.print(TAB);
            }
            String fileName = relativePath.substring(relativePath.lastIndexOf("/") + 1);
            log.info(fileName);

            // 以流的形式读取文件内容执行SQL
            try (InputStream inputStream = resource.getInputStream()) {
                executeSqlStatements(inputStream);
            }
        }
    } catch (IOException e) {
        log.error("Load rules directory failed", e);
    }
}

// 修改原SQL执行方法,接收InputStream参数读取内容
private void executeSqlStatements(InputStream inputStream) throws IOException {
    // 示例:读取流内容为SQL字符串,可替换为你原有逐行读取逻辑
    String sqlContent = org.apache.commons.io.IOUtils.toString(inputStream, StandardCharsets.UTF_8);
    // 原有SQL执行逻辑保持不变即可
}

注意事项

  • 原有代码中字符串比较使用==不符合Java语法规范,字符串内容比较需使用equals()方法,本次优化采用endsWith()直接判断后缀,逻辑更稳妥。
  • 确保构建配置中没有排除src/main/resources/rules目录的打包规则,默认Spring Boot会自动打包该目录下的所有资源。
  • 如果需要完全还原原有先打印目录、再打印子文件的层级展示效果,可以先将扫描到的资源路径整理为树形结构,再递归遍历输出即可。

内容的提问来源于stack exchange,提问作者Pratik Shekhar

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 10:30:01