【问题标题】:getResourceAsStream returns null in one case but not another, with same classpathsgetResourceAsStream 在一种情况下返回 null 但在另一种情况下不返回,具有相同的类路径
【发布时间】:2015-03-26 17:34:12
【问题描述】:

我有同一个应用程序的两个衍生版本,比如版本 (A) 和 (B)。它们每个都包含项目: (1) test-data-war,有target/test-classes/log4j.properties,(2) test-kernel,有target/test-classes/log4j.propertiestarget/test-classes/test.properties

当我在 (1) 中运行特定的 jUnit 测试时,它会调用 (2) 中的一个方法,该方法调用 Thread.currentThread().getContextClassLoader().getResourceAsStream(resourceName); 在 (A) 中,resourceName 为“log4j.properties”,结果不为空(1)中的路径,但resourceName 为“test.properties”,结果为空。在 (B) 中,resourceName 为“log4j.properties”时,(1) 中的路径不为空,resourceName 为“test.properties”时,(2) 中的路径不为空。

为什么Thread.currentThread().getContextClassLoader().getResourceAsStream("test.properties"); 在 (A) 中为空?起初,我认为类路径可能不同,但 (1) 和 (2) 的类路径相同。

编辑: 以下是 (1) 的 .classpath 文件:

<?xml version="1.0" encoding="UTF-8"?>
<classpath>
    <classpathentry kind="src" output="target/classes" path="src/main/java">
        <attributes>
            <attribute name="optional" value="true"/>
            <attribute name="maven.pomderived" value="true"/>
        </attributes>
    </classpathentry>
    <classpathentry excluding="**" kind="src" output="target/classes"    path="src/main/resources">
        <attributes>
            <attribute name="maven.pomderived" value="true"/>
        </attributes>
    </classpathentry>
     <classpathentry kind="src" output="target/test-classes"  path="src/test/java">
        <attributes>
            <attribute name="optional" value="true"/>
            <attribute name="maven.pomderived" value="true"/>
        </attributes>
     </classpathentry>
    <classpathentry excluding="**" kind="src" output="target/test-classes" path="src/test/resources">
        <attributes>
            <attribute name="maven.pomderived" value="true"/>
        </attributes> 
    </classpathentry>
    <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6">
        <attributes>
             <attribute name="maven.pomderived" value="true"/>
        </attributes>
    </classpathentry>
    <classpathentry kind="con" pat h="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
        <attributes>
            <attribute name="maven.pomderived" value="true"/>
            <attribute name="org.eclipse.jst.component.dependency" value="/WEB-INF/lib"/>
        </attributes>
    </classpathentry>
    <classpathentry kind="output" path="target/classes"/>
</classpath>

这是 (2) 的 .classpath 文件的样子:

<?xml version="1.0" encoding="UTF-8"?>
<classpath>
    <classpathentry kind="src" output="target/classes" path="src/main/java">
        <attributes>
            <attribute name="optional" value="true"/>
            <attribute name="maven.pomderived" value="true"/>
        </attributes>
    </classpathentry>
    <classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources">
        <attributes>
            <attribute name="maven.pomderived" value="true"/>
        </attributes>
    </classpathentry>
     <classpathentry kind="src" output="target/test-classes" path="src/test/java">
         <attributes>
            <attribute name="optional" value="true"/>
            <attribute name="maven.pomderived" value="true"/>
          </attributes>
    </classpathentry>
    <classpathentry excluding="**" kind="src" output="target/test-classes" path="src/test/resources">
        <attributes>
            <attribute name="maven.pomderived" value="true"/>
         </attributes> 
    </classpathentry>
    <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6">
        <attributes>
            <attribute name="maven.pomderived" value="true"/>
        </attributes>
     </classpathentry>
     <classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
        <attributes>
           <attribute name="maven.pomderived" value="true"/>
            <attribute name="org.eclipse.jst.component.nondependency" value=""/>
        </attributes> 
    </classpathentry>
    <classpathentry kind="output" path="target/classes"/>
</classpath>

【问题讨论】:

  • 您需要仔细检查所有断言,包括这些文件在两个 JAR 和类路径中是否存在。
  • 我没有看到 (A) 或 (B) 的目标 JAR 中的文件,但不同版本的“.classpath”文件是相同的。

标签: java eclipse maven junit contextclassloader


【解决方案1】:

模块test-kernel 中的测试类路径中的资源对于模块test-data-war 不可见。仅当您将 src/main/resources 下的资源作为依赖项添加到另一个模块时,模块才会导出它们。

令人困惑的是 Eclipse 和 Maven 在这方面存在分歧。在 Eclipse 中,模块的整个类路径都是可见的(也是测试资源)。但是当你在 Maven 中运行相同的测试时,测试资源会突然消失。这是因为 Eclipse 没有“测试类路径”的概念。

如果mvn dependency:tree 显示有差异,那么您需要检查文件pom.xml 中的模块。

【讨论】:

  • 我认为你搞混了。 (A) 和 (B) 是应用程序的独立分支。 (1) 和 (2) 是他们各自拥有的项目。对于 (B),我看到 (2) 是 (1) 的依赖项,但对于 (A) 似乎并非如此。我不知道为什么,因为 (A) 和 (B) 的所有配置似乎都相同。
  • 当您同时运行mvn dependency:tree 时,您发现有什么不同吗?
  • (B) 表示它还从 (2) 下载 POM,但 (A) 没有!我该如何更改?
  • 除此之外,一切似乎都一样,除了其他一些 jar 版本。我应该在 (2) jar 中查找可能不同的文件吗?
  • 是的,依赖项在pom.xml中指定。
【解决方案2】:

在 (B) 中,eclipse 对 (2) 有一个额外的依赖关系,导致 Thread.currentThread().getContextClassLoader().getResourceAsStream("test.properties") 不返回 null。它实际上应该返回 null(即在 (2) 中找不到 test.properties)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-03-31
    • 2023-03-10
    • 1970-01-01
    • 2017-08-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多