1. 概述

在这个教程中,我们将学习如何在Maven构建失败后恢复它。我们将了解如何跳过已经成功构建的模块,从而直接定位到问题出现的地方。

2. 示例设置

让我们构建一个多模块Maven项目父项目称为resume-from,子项目有两个:libbusiness。为了演示,我们暂时让lib项目为空。然而,business项目包含一个名为src/main/java/Main.java的文件,里面只有一个简单的Hello World程序。现在,我们在business模块中添加对lib的依赖:

<dependency>
    <groupId>com.baeldung</groupId>
    <artifactId>lib</artifactId>
    <version>1.0-SNAPSHOT</version>
</dependency>

目前,项目的结构是正确的,所以我们可以成功构建它:

$ mvn clean install
[...]
[INFO] Reactor Summary for resume-from 1.0-SNAPSHOT:
[INFO]
[INFO] resume-from ........................................ SUCCESS [  1.749 s]
[INFO] lib ................................................ SUCCESS [  2.021 s]
[INFO] business ........................................... SUCCESS [  0.991 s]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[...]

3. 在运行install阶段时

现在,我们去掉Main.java文件中的分号。这会导致business子模块的构建失败:

$ mvn clean install
[...]
[INFO] Reactor Summary for resume-from 1.0-SNAPSHOT:
[INFO]
[INFO] resume-from ........................................ SUCCESS [  1.186 s]
[INFO] lib ................................................ SUCCESS [  0.984 s]
[INFO] business ........................................... FAILURE [  0.334 s]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  2.809 s
[INFO] Finished at: 2023-06-20T16:15:13+02:00
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project business: Compilation failure
[ERROR] [...]/resume-from/business/src/main/java/Main.java:[4,43] ';' expected
[...]
[ERROR] After correcting the problems, you can resume the build with the command
[ERROR]   mvn <args> -rf :business

由于lib子模块已经成功构建,修复问题后希望跳过它的构建就很有意义。正如Maven错误消息所说,我们可以使用-rf选项从给定模块恢复反应器构建。现在,我们修复Main.java文件并尝试这样做:

$ mvn clean install -rf :business
[INFO] Scanning for projects...
[INFO]
[INFO] -----------------------< com.baeldung:business >------------------------
[INFO] Building business 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[...]
------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  1.318 s
[INFO] Finished at: 2023-06-20T17:21:07+02:00
[INFO] ------------------------------------------------------------------------

如预期,这次只构建了business子模块。实际上,-rf--resume-from的简写形式,所以我们也可以这样写:

$ mvn clean install --resume-from :business

4. 当不运行install

假设我们现在没有运行Maven的install,而是在早期的阶段停止构建。为了展示这一点,我们可以回到Main.java文件损坏的情况。同时,我们清空本地仓库并运行package阶段:

$ mvn clean package
[...]
[INFO] Reactor Summary for resume-from 1.0-SNAPSHOT:
[INFO]
[INFO] resume-from ........................................ SUCCESS [  0.108 s]
[INFO] lib ................................................ SUCCESS [  0.709 s]
[INFO] business ........................................... FAILURE [  0.316 s]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1.216 s
[INFO] Finished at: 2023-06-20T17:49:59+02:00
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.1:compile (default-compile) on project business: Compilation failure
[ERROR] [...]/resume-from/business/src/main/java/Main.java:[4,43] ';' expected
[...]
[ERROR] After correcting the problems, you can resume the build with the command
[ERROR] mvn <args> -rf :business

不出所料,我们得到了相同的编译错误。错误信息给出同样的提示,即修复问题后使用-rf选项。于是,我们修复问题并运行命令:

$ mvn clean package -rf :business
[INFO] Scanning for projects...
[INFO]
[INFO] -----------------------< com.baeldung:business >------------------------
[INFO] Building business 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[WARNING] The POM for com.baeldung:lib:jar:1.0-SNAPSHOT is missing, no dependency information available
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  0.187 s
[INFO] Finished at: 2023-06-20T17:56:34+02:00
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal on project business: Could not resolve dependencies for project com.baeldung:business:jar:1.0-SNAPSHOT: Could not find artifact com.baeldung:lib:jar:1.0-SNAPSHOT -> [Help 1]

由于我们没有运行install阶段,在第一次构建时lib子模块并没有安装到本地仓库。因此,当Maven尝试恢复构建时,找不到lib模块的 artefact。理论上,我们可以通过在命令行中添加--also-make选项来解决这个问题。--also-make应该会构建business依赖的所有项目。然而,Maven 3存在一个bug,当与--resume-from一起使用时,--also-make被忽略【参见MNG-6863】。

这个bug将在即将发布的Maven 4中修复。然而,在此期间,我们无法在这种情况下从特定模块恢复反应器。不幸的是,我们需要重新构建整个项目:

$ mvn clean package
[...]
[INFO] Reactor Summary for resume-from 1.0-SNAPSHOT:
[INFO]
[INFO] resume-from ........................................ SUCCESS [  0.109 s]
[INFO] lib ................................................ SUCCESS [  0.660 s]
[INFO] business ........................................... SUCCESS [  0.436 s]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[...]

5. 总结

在这篇文章中,我们了解了如何在Maven构建失败后跳过部分构建。当我们将子模块安装到本地仓库时,可以使用-rf选项。另一方面,如果不安装它们,由于Maven的一个bug,我们需要重新构建整个项目。代码示例可在GitHub上找到。