未加载类路径的Groovy资源

时间:2013-11-26 09:37:58

标签: groovy resources classloader

大家好日子。

我在我的groovy项目中使用spock框架进行测试(IDE - Intellij Idea 12.6)。我的spock规范类将文件名传递给groovy对象进行处理(该文件肯定在classpath中),但是当我尝试以这种方式获取该文件时

    def resource = getClass().getClassloader().getResourceAsStream(filepath)
    assert resource != null : "No input stream found for path ${filepath}"
    def rootNode = new XmlParser().parse(resource)

然后resource == null

我尝试调试,在Expression Evaluation窗口中,此代码getClass().getResource(fileName)返回资源。

我尝试检查在第一种情况下使用的类加载器(在使用代码的类中)和第二种情况(表达式评估窗口)。

在第一种情况下,类加载器是sun.misc.Launcher$AppClassLoader@18dabf1,但在Expression Evaluation窗口中,classloader是groovy.lang.GroovyClassLoader$InnerLoader@1e69757我想这就是我的资源为空的原因。

有人可以指导我做错了什么以及如何加载该资源文件?

更新

更改了资源文件的解析方式。当filepath - 文件的完整路径有效时,如果filepath只是文件名而且该文件在classpath中,那么resource == null

UPDATE2

更改加载资源文件的方式,清理依赖项位并且一切正常,我想昨天不是我的一天。

3 个答案:

答案 0 :(得分:7)

这个问题很可能与Spock无关。很难从远处说出导致它的原因,但最安全的阅读资源方式是getClass().getClassLoader().getResourceAsStream()Thread.currentThread().getContextClassLoader().getResourceAsStream(),具体取决于环境。

不确定执行new File(resource)时Groovy会做什么,因为没有File(URL)构造函数(只有File(URI)构造函数)。在任何情况下,应尽可能避免从类路径中获取File

答案 1 :(得分:3)

这可能是因为Groovy可能会以与您认为正在发生的事情不同的方式解释对象的类。请参阅以下其他StackOverflow项:

Why does groovy .class return a different value than .getClass()

当类错误时,ClassLoader可能会被bootstrap加载器和getClassLoader返回null。

所以不要使用像

这样的语句
def resource = getClass().getClassloader().getResourceAsStream(filepath)

使用类似

的语句指定实际的类
def resource = MyClass.class.getClassLoader().getResourceAsStream(filePath)

在几乎相同的情况下为我工作。

答案 2 :(得分:0)

def resource = MyClass.class.getResourceAsStream(fileName)

或者如果您希望文件的内容为字符串:

def str = new String(MyClass.class.getResourceAsStream(fileName).readAllBytes(), StandardCharsets.UTF_8)

请注意:

  1. 使用的是MyClass,而不是this.getClass();
  2. 在资源中,您必须创建与类的包相同的目录结构,并将文件放在那里;
  3. fileName 只是文件名,没有任何路径;
  4. 您必须清理并重建您的项目。