1. 概述

在这个教程中,我们将快速了解Maven反应器的基本概念及其在Maven生态系统中的作用。我们将首先介绍反应器,然后设置一个简单的多模块Maven项目示例,它包含模块间的依赖关系,并观察反应器如何处理构建依赖。我们将讨论一些可用的标志,以进一步调整Maven反应器的行为。最后,我们将总结使用反应器的一些优点。

2. Maven反应器基础

Maven反应器是Maven内置的一部分,负责管理项目依赖和构建。 它负责执行Maven构建并确保项目按照依赖关系的正确顺序进行构建。在复杂的多模块项目中,特别是有许多跨模块依赖的情况下,Maven反应器的优势更为明显。

反应器使用有向无环图(DAG)来确定项目的构建顺序。

作为Maven核心的一部分,它执行以下功能:

  • 收集所有可构建的模块
  • 将项目组织成适当的构建序列
  • 顺序执行选定的项目

4. 示例用例

设想一个开发患者信息管理web应用的项目,它包含三个模块:

  1. patient-web模块:作为应用程序的用户界面
  2. patient-data模块:处理所有数据库CRUD操作
  3. patient-domain模块:包含应用程序使用的领域实体

在这个项目中,patient-web模块依赖于其他两个模块,因为它从持久存储获取和显示数据。另一方面,patient-data模块依赖于patient-domain模块,因为它需要访问领域实体来执行CRUD操作。值得注意的是,patient-data模块与其他两个模块独立。

4.1. Maven设置

为了实现简单示例,我们设置一个多模块项目sample-reactor-project,包含三个模块,每个模块都对应上述目的:


点击此处查看大图

此时,让我们查看项目POM

<artifactId>maven-reactor</artifactId>
<version>1.0-SNAPSHOT</version>
<name>maven-reactor</name>
<packaging>pom</packaging>
<modules>
    <module>patient-web</module>
    <module>patient-data</module>
    <module>patient-domain</module>
</modules>

这里定义了一个多模块项目,三个模块都在<module>标签内声明于项目pom中。

现在,看看patient-data模块的POM

<artifactId>patient-data</artifactId>
<name>patient-data</name>
<parent>
    <groupId>com.baeldung</groupId>
    <artifactId>maven-reactor</artifactId>
    <version>1.0-SNAPSHOT</version>
</parent>
<dependencies>
    <dependency>
        <groupId>com.baeldung</groupId>
        <artifactId>patient-domain</artifactId>
        <version>1.0-SNAPSHOT</version>
    </dependency>
</dependencies>

在这里,可以看到patient-data依赖于patient-domain

对于我们的用例,假设patient-domain模块独立于其他模块,可以独立构建。其POM如下:

<artifactId>patient-domain</artifactId>
<name>patient-domain</name>
    <parent>
        <groupId>com.baeldung</groupId>
        <artifactId>maven-reactor</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>
</project>

最后,patient-web应从patient-datapatient-domain模块获取依赖:

<artifactId>patient-web</artifactId>
<version>1.0-SNAPSHOT</version>
<name>patient-web</name>
    <parent>
        <groupId>com.baeldung</groupId>
        <artifactId>maven-reactor</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <dependencies>
        <dependency>
            <groupId>com.baeldung</groupId>
            <artifactId>patient-data</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    <dependency>
        <groupId>com.baeldung</groupId>
        <artifactId>patient-domain</artifactId>
        <version>1.0-SNAPSHOT</version>
    </dependency>
</dependencies>

4.2. Maven反应器的实际应用

要在实际中查看反应器的工作,请转到项目父目录(maven-reactor)并执行mvn clean install

这时,Maven将使用反应器执行以下任务:

  1. 收集项目中的所有可用模块(在这个例子中,包括patient-webpatient-datapatient-domain
  2. 根据它们的依赖关系确定正确的构建顺序(在这种情况下,patient-domain必须先于patient-datapatient-data必须先于patient-web
  3. 按照正确的顺序逐个构建模块,确保依赖关系得到正确解决

以下是成功的构建顺序:


点击此处查看大图

5. 调整反应器

尽管反应器默认集成在Maven中,但仍然可以通过使用几个命令行选项来修改其行为。这些选项至关重要,因为它们允许我们控制反应器如何构建我们的项目。一些关键选项包括:

  • --resume-from: 如果构建过程中某模块失败,可以从指定的项目恢复构建
  • --also-make: 构建指定的项目及其依赖于它们的任何项目
  • --also-make-dependents: 构建指定的项目以及依赖于它们的任何项目
  • --fail-fast(默认):只要模块构建失败,就立即停止整体构建
  • --fail-at-end: 即使某个模块构建失败,也会继续反应器构建,并在末尾报告所有失败的模块
  • --non-recursive: 使用此选项,即使项目pom声明了其他模块,也可以禁用反应器构建,仅构建当前目录中的项目

通过这些选项,我们可以精细调整反应器的行为,以按需构建项目。

6. 总结

在这篇文章中,我们简要介绍了在Apache Maven生态系统中使用Maven反应器构建复杂多模块项目的好处,它为开发者移除了处理依赖关系和构建顺序的责任,并减少了构建时间。如往常一样,本文中的所有代码示例均可在GitHub上找到。