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

如何获取Spring Boot项目jar包内resources资源文件夹的路径

问题根因
  1. src/main/resources仅为开发阶段的源码目录,Maven构建打包后该目录不会保留在最终的jar包内,resources下的所有文件会被归档到jar包的BOOT-INF/classes/路径下,属于jar包内部的嵌套资源,不是操作系统文件系统中的独立文件/目录,不可能通过Paths.get直接拿到对应文件系统的Path实例。
  2. 第二种写法抛出空指针的两个原因:
    • Spring Boot使用自定义的LaunchedURLClassLoader加载应用内部的类和资源,ClassLoader.getSystemClassLoader()拿到的系统类加载器无法识别jar包内的应用资源,会直接返回null
    • 就算拿到了资源的URI,jar包内资源的URI格式为jar:file:/xxx/your-app.jar!/BOOT-INF/classes/templates,Path.of仅支持file协议的URI,无法解析jar协议的资源地址,依然会报错
解决方案

根据你的使用场景选择对应实现:

场景1:仅需要读取资源内容,不需要拿到文件系统Path

推荐直接使用Spring官方提供的ResourceLoader,天然适配IDE、jar包等所有运行环境:

import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.stereotype.Component;

@Component
public class ResourceService {
    private final ResourceLoader resourceLoader;

    // Spring会自动注入ResourceLoader实例
    public ResourceService(ResourceLoader resourceLoader) {
        this.resourceLoader = resourceLoader;
    }

    public void readTemplateResource() throws IOException {
        // classpath:前缀对应resources根目录,直接写相对路径即可
        Resource templatesResource = resourceLoader.getResource("classpath:templates/");
        // 直接获取输入流读取内容,不需要关心资源的实际存储形式
        try (var inputStream = templatesResource.getInputStream()) {
            // 你的资源处理逻辑
        }
    }
}

场景2:必须拿到文件系统的Path实例(如需要遍历目录、修改资源等操作)

jar包内的嵌套资源无法直接映射为文件系统Path,需要先将资源解压到外部临时目录再操作:

public Path getTemplatesPath() throws IOException {
    Resource templatesResource = resourceLoader.getResource("classpath:templates/");
    // 创建临时目录存放解压后的资源
    Path tempDir = Files.createTempDirectory("app_templates_");
    
    try {
        // IDE环境走文件系统路径直接复制
        Path sourcePath = Path.of(templatesResource.getURI());
        copyDirectory(sourcePath, tempDir);
    } catch (FileSystemNotFoundException e) {
        // jar环境走流读取解压
        extractResourceToDir(templatesResource, tempDir);
    }
    
    return tempDir;
}

// 目录复制工具方法,可根据需要自行实现递归多层目录的逻辑
private void copyDirectory(Path source, Path target) throws IOException {
    Files.walk(source)
            .forEach(path -> {
                try {
                    Path targetPath = target.resolve(source.relativize(path));
                    if (Files.isDirectory(path)) {
                        Files.createDirectories(targetPath);
                    } else {
                        Files.copy(path, targetPath);
                    }
                } catch (IOException ex) {
                    throw new RuntimeException(ex);
                }
            });
}

// jar环境资源解压工具方法,可根据实际资源结构调整
private void extractResourceToDir(Resource resource, Path targetDir) throws IOException {
    // 此处按你的实际资源结构实现流读取写入逻辑即可
}
注意事项
  • 不要硬编码开发阶段的源码路径,该路径仅存在于你的工程源码目录,打包部署后完全不存在
  • 不要直接使用系统类加载器读取Spring Boot应用的内部资源,Spring的ResourceLoader已经屏蔽了不同运行环境的资源加载差异,是最优选择
  • jar包内的资源默认是只读的,如果有资源修改需求,必须将资源存储到jar包外的独立目录(如应用工作目录、系统临时目录等)

内容的提问来源于stack exchange,提问作者Elmar Brauch

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 10:54:03