Java:如何列出Jar包中resources目录下的直接子目录
解决Maven项目中IDE与Jar环境兼容的资源目录子项获取问题
我之前也踩过这个坑——IDE里跑起来顺风顺水的代码,打包成Jar就直接失效,核心原因就是两种环境下资源的存储逻辑完全不一样:IDE里是真实的文件系统目录,而Jar里是压缩包内的条目。下面给你一套能同时兼容两种场景的解决方案,专门用来获取dir1的直接子目录名称(比如你的subdir1、subdir2):
核心实现代码
这里写一个工具类,把两种环境的处理逻辑封装起来:
import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; import java.net.URL; import java.nio.file.*; import java.util.ArrayList; import java.util.List; import java.util.stream.Stream; public class ResourceDirectoryUtils { public static List<String> getDirectSubdirectories(String parentDir) throws IOException, URISyntaxException { List<String> subDirNames = new ArrayList<>(); // 获取目标目录的资源URL URL resourceUrl = Thread.currentThread().getContextClassLoader().getResource(parentDir); if (resourceUrl == null) { throw new IllegalArgumentException("指定的目录不存在: " + parentDir); } URI resourceUri = resourceUrl.toURI(); // 区分是文件系统资源(IDE环境)还是Jar包内资源 if ("file".equals(resourceUri.getScheme())) { // IDE环境:直接操作本地文件系统 Path parentPath = Paths.get(resourceUri); // 遍历目录,过滤出子目录并收集名称 try (Stream<Path> pathStream = Files.list(parentPath)) { pathStream.filter(Files::isDirectory) .map(path -> path.getFileName().toString()) .forEach(subDirNames::add); } } else if ("jar".equals(resourceUri.getScheme())) { // Jar包环境:创建临时文件系统访问Jar内条目 FileSystem jarFileSystem = FileSystems.newFileSystem(resourceUri, null); Path parentPath = jarFileSystem.getPath(parentDir); try (Stream<Path> pathStream = Files.list(parentPath)) { pathStream.filter(Files::isDirectory) .map(path -> path.getFileName().toString()) .forEach(subDirNames::add); } finally { // 用完记得关闭文件系统,避免资源泄漏 jarFileSystem.close(); } } else { throw new UnsupportedOperationException("不支持的资源类型: " + resourceUri.getScheme()); } return subDirNames; } // 测试用例,直接运行就能看到结果 public static void main(String[] args) { try { List<String> subDirs = getDirectSubdirectories("dir1"); System.out.println("dir1的直接子目录:"); subDirs.forEach(System.out::println); } catch (Exception e) { e.printStackTrace(); } } }
关键细节说明
- 类加载器选择:用
Thread.currentThread().getContextClassLoader()而不是当前类的getResource(),能适配更复杂的类加载场景(比如模块化项目、自定义类加载器) - 环境区分逻辑:通过URI的
scheme判断是file(IDE本地文件)还是jar(压缩包内资源),分别处理 - Jar环境的特殊处理:Jar包本质是压缩文件,需要创建临时的
FileSystem才能像访问本地目录一样遍历内部条目,用完必须关闭 - 资源路径正确性:默认情况下Maven会把
src/main/resources下的内容打包到Jar根目录,所以调用时直接传dir1即可;如果你的Maven资源配置有自定义路径,要对应调整参数
注意事项
- 确保Maven的
pom.xml没有排除dir1及其子目录,默认的资源配置会包含所有src/main/resources下的内容 - 异常处理可以根据业务需求调整,比如返回空列表而不是抛出异常,或者添加日志输出
- 如果是JDK9+的模块化项目,需要在
module-info.java中添加对java.nio.file的依赖
内容的提问来源于stack exchange,提问作者lubik
相关产品推荐
相关产品推荐

