类路径和maven配置文件

时间:2016-03-04 06:01:32

标签: maven classpath maven-profiles

我有3个罐子,即jar1,jar2,jar3。

在jar1中有一些代码从类路径中读取文件。但是该文件不会出现在jar1的类路径中。相反,jar2将被插入,因为jar1和jar2类路径的依赖将包含该文件。

我有jar3,它的类路径中也包含相同的文件,但我会在jar1的test中为jar3声明范围为pom.xml

现在,当执行测试用例时,我们怎么能告诉maven始终从jar3(作为测试的范围)类路径获取文件,尽管jar2是作为主要依赖项给出的(范围不是测试)?

这可以通过maven配置文件吗?如果是,我们如何指定它? 或者我们可以使用maven-resources-plugin在测试范围内复制文件吗?

如果在作为依赖项的多个jar中存在相同的文件,那么将如何设置classpath?

示例jar1 pom.xml

<dependencies>
        <dependency>
            <groupId>com.test</groupId>
            <artifactId>jar2</artifactId>
            <version>0.1-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>com.test</groupId>
            <artifactId>jar3</artifactId>
            <version>0.1-SNAPSHOT</version>
            <scope>test</scope>
        </dependency>
</dependencies>

jar2和jar3都有资源文件。

问题:哪个会被接收?为什么?

1 个答案:

答案 0 :(得分:1)

如果依赖关系在依赖关系树中处于同一级别,则根据Maven Dependency Mediation doc,pom中的声明顺序将获胜:

  

请注意,如果两个依赖项版本在依赖关系树中处于相同的深度,那么直到Maven 2.0.8没有定义哪一个会赢,但是从Maven 2.0.9开始,它就是声明中的顺序。计数:第一个声明获胜

因此,在您的情况下,两个依赖项在依赖关系树中处于同一级别(第一级,在POM中声明),compile范围将在test范围内出现,因此jar2会赢,因为你在你的POM中首先声明它(根据你发布的剪辑)。

如果您希望始终从jar3加载文件,但仅在测试期间加载,只需先在依赖项中声明jar3即可。它不会影响最终的可交付成果(位于test范围内),但它会定义类路径的顺序以进行测试,从而为您提供预期的方案。你不需要Maven配置文件。

一个简单的测试用例来验证它:

让我们将属性file.properties定义为Maven项目的src\main\resources。项目resource-provider(artifactId)的文件如下所示:

property=from-resource-provider

如下面的项目resource-provider2(artifactId):

property=from-resource-provider2

注意:将相同的文件名分成两个具有不同内容的不同项目。

然后在一个消费者项目(resource-consumer)中,我们可以得到以下示例JUnit测试用例:

public class MainTest {

    @Test
    public void checkClassPath() {
        InputStream is = MainTest.class.getResourceAsStream("/file.properties");
        Scanner s = new Scanner(is);
        System.out.println(s.nextLine());
    }

}

对于resource-consumer的以下依赖关系:

<dependencies>
    <dependency>
        <groupId>com.sample</groupId>
        <artifactId>resource-provider2</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>com.sample</groupId>
        <artifactId>resource-provider</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </dependency>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.11</version>
        <scope>test</scope>
    </dependency>
</dependencies>

测试执行的输出将是:

-------------------------------------------------------  
 T E S T S  
-------------------------------------------------------  
Running com.sample.MainTest   
property=from-resource-provider2  
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.051 sec  

因此,声明的第一个依赖项resource-provider2赢了(注意范围,test)。

将依赖关系顺序更改为:

<dependencies>
    <dependency>
        <groupId>com.sample</groupId>
        <artifactId>resource-provider</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </dependency>
    <dependency>
        <groupId>com.sample</groupId>
        <artifactId>resource-provider2</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.11</version>
        <scope>test</scope>
    </dependency>
</dependencies>

而是提供以下输出:

-------------------------------------------------------   
 T E S T S   
-------------------------------------------------------   
Running com.sample.MainTest   
property=from-resource-provider   
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.07 sec

注意:这次resource-provider赢了,因为它首先被声明,因为compile范围也是test范围的一部分,而事实恰恰相反。