You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Spring应用打包成Jar后如何获取指定文件夹下的文件路径列表

解决Jar包中获取/static开头的资源路径问题

你的问题核心在于Jar包内的资源不是磁盘上的真实文件,所以用File对象访问完全行不通;而且IDE环境下的路径带src/main/resources,也不符合你要的/static格式。下面给你一套能同时兼容IDE和Jar运行环境的解决方案:

问题根源

在IDE中运行时,src/main/resources下的资源是磁盘上的真实文件,所以File能找到;但打包成Jar后,这些资源被压缩到Jar包内部,变成了Jar的条目(不是独立文件),File对象无法识别这种结构,自然返回错误路径或null。

解决方案:兼容IDE和Jar的资源路径获取

我们可以通过判断运行环境(File/Jar协议),分别处理资源遍历,最终生成/static开头的路径。

工具类代码实现

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

public class StaticResourceHelper {

    /**
     * 获取指定basePath下的所有资源路径,格式为/static/xxx
     * @param basePath 从classpath根开始的基础路径(比如"static/json/networks/pools")
     * @return 符合要求的路径列表
     */
    public static List<String> getStaticResourcePaths(String basePath) {
        List<String> resultPaths = new ArrayList<>();
        URL resourceUrl = StaticResourceHelper.class.getClassLoader().getResource(basePath);
        
        if (resourceUrl == null) {
            System.err.println("指定的资源路径不存在:" + basePath);
            return resultPaths;
        }

        String protocol = resourceUrl.getProtocol();
        if ("file".equals(protocol)) {
            // IDE运行环境:直接遍历磁盘目录
            File folder = new File(resourceUrl.getFile());
            traverseFileSystemFolder(folder, basePath, resultPaths);
        } else if ("jar".equals(protocol)) {
            // Jar运行环境:读取Jar包内的条目
            handleJarResource(resourceUrl, basePath, resultPaths);
        }

        return resultPaths;
    }

    // 遍历磁盘目录,生成/static开头的路径
    private static void traverseFileSystemFolder(File folder, String currentBasePath, List<String> paths) {
        File[] files = folder.listFiles();
        if (files == null) return;

        for (File file : files) {
            if (file.isDirectory()) {
                traverseFileSystemFolder(file, currentBasePath + "/" + file.getName(), paths);
            } else {
                String relativePath = currentBasePath + "/" + file.getName();
                paths.add("/" + relativePath);
            }
        }
    }

    // 处理Jar包内的资源条目
    private static void handleJarResource(URL resourceUrl, String basePath, List<String> paths) {
        // 解析Jar包的路径(格式:jar:file:/xxx/your-app.jar!/static/xxx)
        String jarFullPath = resourceUrl.getPath().substring(5, resourceUrl.getPath().indexOf("!"));
        
        try (JarFile jarFile = new JarFile(jarFullPath)) {
            Enumeration<JarEntry> jarEntries = jarFile.entries();
            while (jarEntries.hasMoreElements()) {
                JarEntry entry = jarEntries.nextElement();
                String entryName = entry.getName();
                
                // 筛选:以basePath开头、且不是目录的条目
                if (entryName.startsWith(basePath) && !entry.isDirectory()) {
                    paths.add("/" + entryName);
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

使用示例

public class Main {
    public static void main(String[] args) {
        // 获取/static/json/networks/pools下的所有文件路径
        List<String> resourcePaths = StaticResourceHelper.getStaticResourcePaths("static/json/networks/pools");
        
        // 输出结果,格式就是你要的/static/xxx
        for (String path : resourcePaths) {
            System.out.println(path);
            // 示例输出:/static/json/networks/pools/network.json
        }

        // 如果要加载资源,直接用这个路径即可
        // InputStream is = Main.class.getResourceAsStream(path);
    }
}

关键细节说明

  1. classpath路径对应src/main/resources下的内容会被maven打包到Jar的根目录,所以static目录直接在classpath根下,用classLoader.getResource("static/xxx")就能找到。
  2. 路径格式适配:不管是IDE还是Jar环境,最终生成的路径都是/static/xxx,完全符合你配合Class加载资源的需求(比如Class.getResourceAsStream("/static/xxx"))。
  3. 资源加载兼容性:生成的路径可以直接用于Class.getResource()ClassLoader.getResource(),无需额外转换。

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

火山引擎 最新活动