Class 路径和 maven 配置文件

Class Path and maven profile

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

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

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

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

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

如果相同的文件存在于作为依赖项的多个 jar 中,将如何设置类路径?

示例 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都有资源文件

问题:哪个会被拾取,为什么?

如果您的依赖项在依赖项树中处于同一级别,则根据 Maven Dependency Mediation 文档:

,您的 pom 中的声明顺序将优先

Note that if two dependency versions are at the same depth in the dependency tree, until Maven 2.0.8 it was not defined which one would win, but since Maven 2.0.9 it's the order in the declaration that counts: the first declaration wins

所以在你的情况下,两个依赖关系在依赖关系树中处于同一级别(第一级别,在 POM 中声明)并且 compile 范围将存在于任何时候 test 范围,因此 jar2 会赢,因为您首先在 POM 中声明了它(根据您发布的片段)。

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


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

让我们在 Maven 项目的 src\main\resources 中定义一个 属性 file.properties。项目 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作用域的一部分,反之则不然。