如何解决多模块项目中模块之间的依赖关系?

Posted

技术标签:

【中文标题】如何解决多模块项目中模块之间的依赖关系?【英文标题】:How to resolve dependencies between modules within multi-module project? 【发布时间】:2013-01-19 14:08:37 【问题描述】:

在使用 Maven 一段时间后,我对 Maven 为构建架构带来的许多特性感到兴奋,尤其是依赖关系管理。但是,我一次又一次地遇到一个问题——Maven 如何解决多模块项目之间的依赖关系。我想知道这是否是当前 Maven 实现的大缺陷和/或是否有任何令人满意的解决方法。

假设我有一个多模块 Maven 项目。 Parent pom 包含三个模块——moduleA (jar)、moduleB (jar) 和moduleC(war)。 B 依赖于 A,C 依赖于 B。够简单吗?现在我想在父项目中运行mvn dependency:go-offline,它应该解决所有依赖项并将它们带入本地 .m2 目录。它失败是因为 Maven 抱怨它在作用于模块 B 时无法解决模块 A 的依赖关系。因为所有这些模块都属于一个groupId,所以我什至尝试使用-DexcludeGroupIds=x.y.z 来排除这些模块依赖关系,但它仍然在同一点失败。

我理解 Maven 抱怨的原因 - moduleA 尚未构建,因此当执行脱机目标时,我的本地或内部存储库中没有 moduleA:jar 工件。但恕我直言,插件应该以不同的方式处理这些模块间依赖关系。在这种情况下,它应该简单地忽略它。有人可能会争辩说我可以简单地执行mvn clean install,这会将moduleA:jar 安装到本地存储库中。之后,运行mvn dependency:go-offline 肯定会起作用。但是这种解决方法违背了这个离线目标的目的。这个插件允许我们在不构建整个项目的情况下解析和拉取依赖项到我们的本地存储库中。我在另一个案例中使用了dependency:copy-dependencies 目标,它也有同样的问题。

我在其他情况下也遇到过类似的问题:"mvn clean generate-source" could not resolve dependencies。当我运行mvn clean compile 时,一切正常,但是当我运行mvn clean generate-source 时,它失败了,因为 Maven 无法解析模块间依赖关系。在这种情况下,这是由 antrun 插件中的@requiresDependencyResolution 引起的。

由于 antrun 插件和依赖插件都在 Maven 世界中非常流行,我相信我不是唯一遇到这个问题的人。有人找到任何解决方案/解决方法吗?

【问题讨论】:

我已投票以“不具建设性”来结束这个问题。它可能写得很有说服力,但是我在那里看不到具体的问题。要求讨论 Maven 在其当前行为中是否“正确”并不适合本网站的问答模型。 Duncan,我也在寻找一种解决方法,而不是先执行 mvn clean install。也许我没有正确地用标题。我的目的是找到解决方案/解决方法,而不是争论 maven 的行为是否正确。 @DuncanJones 我修改了标题和问题以澄清我的意图。感谢您的评论。 @DuncanJones 这个问题在尝试创建多阶段 docker 构建时很痛苦,其中第一层将检索所有必需的外部依赖项,以便在后续调用中缓存它们(除非其中一个 pom文件更改)。 【参考方案1】:

您解释了为什么它不起作用,以便您了解问题。你的问题是它会在找不到 A.jar 时停止,但只有在你开始构建 B 时才会发生这种情况。所以有一种有时有用的策略。

你必须自己弄乱 A。只需构建 A。使用加载依赖项的计划,然后构建它。

构建完成后,您可以继续对 B 和 C 执行相同的操作。逐步进行。

这里要记住的一件事是,有时可以在本地存储库中使用 A 的旧快照构建 B。如果有签名更改或 B 需要的新内容,您只需要在 repo 中构建 A 的新快照。

这里也有一些讨论:Maven Modules + Building a Single Specific Module

当人们的构建时间过长时,通常不会出现这类问题。有几种方法可以加快构建速度:

    获得更快的硬件。构建计算机、磁盘存储或网络速度是典型的组件,与在缓慢构建中浪费时间相比,升级成本更低。 通过不构建不需要重建的东西来加快构建速度。 (例如,我有一个构建,每次都重新构建所有生成的代码。我在构建中添加了一些东西,使其无法这样做,除非生成代码的依赖关系发生变化。) 加快测试速度。有时这意味着将测试分成两部分。第 1 部分是快速测试,第 2 部分是慢速测试。对每个构建运行快速测试,在任何代码签入或发布工件之前运行慢速测试。 将多模块构建分解为 2 个或更多独立构建,并使用人类智能来决定何时重建。当一些 jars 稳定并且不再发生太大变化时,这很有效。 填写您自己的方法以加快构建速度。

【讨论】:

Lee,我喜欢你关于加快构建速度的建议。但是要解决我的主要问题,一次一个地构建一个模块似乎真的很麻烦。我宁愿先在所有模块上执行 mvn clean install,这样我就不需要一次处理一个模块。无论如何,感谢您的意见。【参考方案2】:

我怀疑 Maven 是否可以实现这样的功能。虽然您的项目共享一个共同的父项目并相互依赖,但 Maven 不可能知道在哪里可以找到这些项目以构建它们。它也无法确定是否只需要构建项目,或者您是否为依赖项指定了错误的版本号。

【讨论】:

经过一番研究,我得出了同样的结论。我可以使 mvn 依赖项工作的唯一方法是:将模块的所有工件放在 .m2 文件夹或 maven 企业存储库中。 将工件放入 .m2 是 "mvn install" 如果你不想安装,"mvn package dependency:go-offline" 就可以了。 Petar 创建了issues.apache.org/jira/browse/MDEP-516 问题以寻找更好的替代方案或将其添加到插件的文档中【参考方案3】:

Maven 有一个“反应器”的概念,其中在一次运行中构建的工件(例如maven package)在构建期间可用于依赖解析。例如,如果您的依赖关系图生成构建顺序 moduleA moduleB moduleC,而您执行 mvn package,Maven 将构建 moduleA,打包其工件并将其添加到反应器中,然后构建 moduleB,将其打包并将其添加到反应器中,那么对于moduleC也是一样的。这意味着 moduleB 可以访问 moduleA 的工件以解决依赖关系,而 moduleC 可以访问 moduleA 和 moduleB。这仅在实际构建工件时才有效,即当您运行包目标时。

问题在于,当您因为对工件不感兴趣而没有运行包目标时(对于您的 dependency:go-offline 示例),已处理的模块的工件不会被构建,因此不会添加到反应器中。我也觉得这很烦人;我认为 Maven 应该查看其要构建的模块列表中的 POM 文件并在那里查看;但事实并非如此。

简而言之,您的问题的解决方案是做 mvn package dependency:go-offline 。这不会在您的本地存储库中安装工件(我认为这是非常糟糕的做法),但它在构建期间将它们放入反应器中,这意味着 Maven 将能够从您的 moduleB 到已经构建的 moduleA。缺点是每个模块都会被测试和打包,当你只想做dependency:go-offline时,这是很多工作。

无论如何,希望这会有所帮助。

【讨论】:

这很有帮助。我觉得如果更多的 Maven 菜鸟能够提前意识到这一点,他们就会更容易理解 Maven 以及它的目标 回复:“缺点是每个模块都将被测试和打包,当你只想做依赖时,这是很多工作:去离线。”不要忘记-DskipTests。 ?【参考方案4】:

我在这里创建了一个带有示例项目的 JIRA 票证:

https://issues.apache.org/jira/browse/MDEP-516

请为它投票。

【讨论】:

【参考方案5】:

从 Maven Dependency Plugin v3.1.2 开始,dependency:go-offline 目标将支持这一点。相关的 jira 票证 MDEP-204 和补丁 23b7ca8790ae14175ed8e3a20c75c6274efe5ad8 修复。

【讨论】:

【参考方案6】:

这是 finally been resolved 和 Maven Dependency Plugin 版本 3.1.2。

您可以通过将版本固定在pom.xml 中来确保它已被使用:

<build>
    <pluginManagement>
        <plugins>
            <plugin>
                <artifactId>maven-dependency-plugin</artifactId>
                <version>3.1.2</version>
            </plugin>
       </plugins>
    </pluginManagement>
</build>

【讨论】:

我做到了,但我仍然得到“无法解决项目的依赖关系......”。我需要考虑什么吗? 很难说没有更多细节。这多次为我解决了这个问题。不过,不一定能为每个人解决所有问题。问一个包含更多细节的新问题?

以上是关于如何解决多模块项目中模块之间的依赖关系?的主要内容,如果未能解决你的问题,请参考以下文章

多模块项目构建期间模块之间的 Maven 依赖关系解析

Mojo 开发 - 处理多模块项目中未解决的依赖关系

如何正确地实现Java模块与inter-module Maven构建测试依赖关系

当***模块及其子模块之一作为单独版本单独导入时,如何解决冲突的 go 模块依赖关系?

多模块添加依赖关系

maven中引入其他模块会下载他的依赖吗