【问题标题】:Unable to get file list from standard resource dir in Maven project with Spring PathMatchingResourcePatternResolver无法使用 Spring PathMatchingResourcePatternResolver 从 Maven 项目中的标准资源目录获取文件列表
【发布时间】:2014-04-18 00:47:44
【问题描述】:

注意:根据以下公认的解决方案,这似乎仅与 Spring 的 DefaultResourceLoader 不使用类加载器为资源创建 URL 实例这一事实有关,因此忽略了自定义类加载器

https://jira.spring.io/browse/SPR-8176

我有一个标准的 Maven 项目,它看起来像这样

$ tree
.
├── pom.xml
└── src
    ├── main
    │   ├── java
    │   │   
    │   └── resources
    │       └── application.properties
    └── test
        └── java

我很快就会在资源目录下的目录树中拥有更多资源文件,我想循环访问它们。在其他几篇文章之后,我使用了 Spring Framework 中的 PathMatchingResourcePatternResolver。我写的抓取所有文件名的函数如下

public static List<File> getAllResourceFiles() {
    PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
    Resource[] resources;
    try {
        resources = resolver.getResources("classpath*:.*");
        System.out.println(JsonUtils.objectToJson(resources));
    } catch (IOException e) {
        e.printStackTrace();
    }
    return null;
}

其中objectToJson 是一个简单地使用Jackson 序列化对象的函数。现在,当我编译并运行这个应用程序时,我没有得到任何结果。特别是,我没有看到 application.properties。我该如何完成这项工作?

$ java -jar target/MyApp.one-jar.jar
[]

更新:正如下面评论中所指出的,这是使用 Simon Tuffs 的一个 jar maven 插件。但是,从类路径读取文件的常用方法是有效的。即

MyClass.class.getResourceAsStream("/application.properties");

更新 2:我尝试了以下方法:

resources = resolver.getResources("classpath:**/*.*");

并得到这个堆栈跟踪

java.io.FileNotFoundException: class path resource [] cannot be resolved to URL because it does not exist
at org.springframework.core.io.ClassPathResource.getURL(ClassPathResource.java:178)
at org.springframework.core.io.support.PathMatchingResourcePatternResolver.isJarResource(PathMatchingResourcePatternResolver.java:414)
at org.springframework.core.io.support.PathMatchingResourcePatternResolver.findPathMatchingResources(PathMatchingResourcePatternResolver.java:343)
at org.springframework.core.io.support.PathMatchingResourcePatternResolver.getResources(PathMatchingResourcePatternResolver.java:282)
at com.example.utils.ResourceUtils.getAllResourceFiles(ResourceUtils.java:29)
at com.example.Starter.main(Starter.java:14)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at com.simontuffs.onejar.Boot.run(Boot.java:340)
at com.simontuffs.onejar.Boot.main(Boot.java:166)

Starter.java中的代码是

public static void main(String[] args) { 
    System.out.println(Environment.getProperty("com.example.applicationLogPath"));
    System.out.println(JsonUtils.objectToJson(ResourceUtils.getAllResourceFiles()));
}

第一行成功执行并打印 applicationLogPath 属性的字符串值。第二个导致 FNF 堆栈跟踪。获取属性的代码使用标准方法获取 jar 中文件的输入流。

Environment.class.getResourceAsStream("/application.properties");

【问题讨论】:

  • 那个文件夹结构是打包在 MyApp.jar 里面的?或者更好地说,相对于 MyApp.jar 位置 application.properties 在哪里?
  • 这是一个很好的问题,我正在使用 maven jar 插件和 one jar 插件。我查看了 jar 内部 jar tvf target/MyApp.one-jar.jar,当我提取 jar 的内容时看到了 main/MyApp.jar,并查看了这个 jar$ jar tvf MyApp.jar 我在顶层看到了 application.properties
  • 也就是说,我可以提取特定资源,如InputStream inputStream = MyClass.class.getResourceAsStream("/application.properties");

标签: java spring maven resources classpath


【解决方案1】:

我认为问题出在 OneJar 上。如果您的项目在“one-jar” jar 之外使用,您的项目运行得很好,我已经对其进行了测试(在我评论了正在破坏的 JsonUtils 部分之后)并且我可以看到它正在扫描的文件。看来others have hit this or similar issue 也是如此。另外,我不太确定 Spring(通过那个 JIRA 问题)是否会被更改,以便加载资源以取悦 OneJar。

【讨论】:

  • 哦,这很有趣,我明白了,这就解释了为什么对 class.getResourceAsStream 的正常调用是成功的。
  • ^ 但没有列出内容的机制。
  • 我将相关的 jars 添加到我的类路径中并且没有使用 onejar 插件运行,我仍然得到这个 java.io.FileNotFoundException: class path resource [] cannot be resolved to URL because it does not exist at org.springframework.core.io.ClassPathResource.getURL(ClassPathResource.java:178) at ... 任何想法?我想我已经厌倦了尝试为此使用弹簧
  • 你是对的。我犯了一个错误。控制台上打印的文件来自目录,可执行 jar 不是从 jar 本身启动的。
【解决方案2】:

我认为你正在寻找的是

resources = resolver.getResources("classpath:**/*.*");
                                        // ^ don't need the * here

匹配任何嵌套级别中的每个资源和任何扩展名。

你有什么

resources = resolver.getResources("classpath*:.*");

匹配类路径根目录中没有名称但有任何扩展名的资源。

【讨论】:

  • 嗨 Sotirios,感谢您的回复。我试过了,但我仍然得到java.io.FileNotFoundException: class path resource [] cannot be resolved to URL because it does not exist 而且我仍然能够通过MyApp.class.getResourceAsStream("/application.properties"); 直接获取application.properties 的内容当我像resources = resolver.getResources("classpath*:**/*.*"); 一样将星号添加到类路径时,我没有得到FNF 异常但结果仍然是空的(即 application.properties)。
  • @DavidWilliams 您能否在我的回答后准确地编辑您的问题?同时发布任何被打印的堆栈跟踪。
  • @DavidWilliams jar 的类路径上有什么?
  • 我不确定我是否理解。这是一个胖罐子,所以我没有从罐子外面放任何东西。我是否正确理解了您的问题?
  • @DavidWilliams 尝试直接在 eclispe(或其他 IDE)中运行您的代码,而不是通过 jar。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-11-14
  • 1970-01-01
  • 2021-12-09
  • 1970-01-01
相关资源
最近更新 更多