使用 Maven 构建多模块项目

一、概述

在本教程中,我们将学习如何使用 Maven 构建多模块项目。

首先,我们将讨论什么是多模块项目,并看看遵循这种方法的好处。然后我们将设置我们的示例项目。有关 Maven 的良好介绍,请查看本教程。

2. Maven的多模块项目

多模块项目由管理一组子模块的聚合器 POM 构建。在大多数情况下,聚合器位于项目的根目录中,并且必须具有 pom类型的打包。

子模块是常规的 Maven 项目,它们可以单独构建,也可以通过聚合器 POM 构建。

通过聚合器 POM 构建项目,每个具有与pom不同的打包类型的项目都会生成一个构建的存档文件。

3. 使用多模块的好处

使用这种方法的显着优势是 我们可以减少重复。

假设我们有一个由几个模块组成的应用程序,一个前端模块和一个后端模块。现在想象一下我们对它们进行处理并更改功能,这会影响它们。在这种情况下,如果没有专门的构建工具,我们将不得不分别构建两个组件或编写脚本来编译代码、运行测试并显示结果。然后,当我们在项目中获得更多模块后,它会变得更难管理和维护。

在现实世界中,项目可能需要某些 Maven 插件在构建生命周期中执行各种操作,共享依赖项和配置文件,以及包含其他BOM 项目。

因此,当利用多模块时,我们可以在一个命令中构建应用程序的模块,如果顺序很重要,Maven 会为我们解决。我们还可以与其他模块共享大量配置

4. 父 POM

Maven 以每个 pom.xml 文件都具有隐式父 POM的方式支持继承。它称为 Super POM  ,可以位于 Maven 二进制文件中。这两个文件由 Maven 合并,形成 Effective POM。

我们可以创建自己的 pom.xml 文件,作为父项目。然后我们可以在其中包含所有具有依赖关系的配置,并将其设置为我们子模块的父模块,以便它们继承它。

除了继承之外,Maven 还提供了聚合的概念。利用此功能的父 POM 称为聚合 POM 基本上,这种 POM在其 pom.xml 文件中显式声明其模块。

5. 子模块

子模块或子项目是从父 POM 继承的常规 Maven 项目。正如我们已经知道的,继承让我们与子模块共享配置和依赖关系。但是,如果我们想一次性构建或发布我们的项目,我们必须在父 POM 中明确声明我们的子模块。最终,我们的父 POM 将成为父 POM,以及聚合 POM。

6. 构建应用程序

现在我们了解了 Maven 的子模块和层次结构,让我们构建一个示例应用程序来演示它们。我们将使用 Maven 的命令行界面来生成我们的项目。

这个应用程序将包含三个模块,它们代表:

  • 我们领域的 核心 部分
  • 提供一些 REST API的 Web 服务 
  • 包含 某种面向用户的网络资产的网络应用 程序

由于我们将专注于 Maven,因此这些服务的实现将保持未定义。

6.1。生成父 POM

首先,让我们创建一个父项目

mvn archetype:generate -DgroupId=com.baeldung -DartifactId=parent-project

生成父级后,我们必须打开 位于父级目录中的pom.xml文件并将包装添加为pom

<packaging>pompackaging>

通过将包装设置为pom类型,我们声明该项目将作为父级或聚合器;它不会产生更多的工件。

现在,当我们的聚合器完成后,我们可以生成我们的子模块。

但是,我们需要注意,这是所有要共享的配置所在的位置,最终会在子模块中重复使用。除此之外,我们可以在这里使用dependencyManagement 或 pluginManagement  。

6.2. 创建子模块

由于我们的父 POM 被命名为parent-project,我们需要确保我们在父目录中并运行生成命令:

cd parent-project
mvn archetype:generate -DgroupId=com.baeldung -DartifactId=core
mvn archetype:generate -DgroupId=com.baeldung -DartifactId=service
mvn archetype:generate -DgroupId=com.baeldung -DartifactId=webapp

注意使用的命令。这与我们用于父级的相同。这里的问题是,这些模块是常规的 Maven 项目,但 Maven 认识到它们是嵌套的。当我们将目录切换到parent-project时,发现 parent 有pom 类型的打包,它会相应地修改pom.xml 文件。

parent-project的 pom.xml 中,它将在modules部分中添加所有子模块:

<modules>
    <module>coremodule>
    <module>servicemodule>
    <module>webappmodule>
modules>

在各个子模块的pom.xml中,它将在部分添加父项目:

<parent>
  <artifactId>parent-projectartifactId>
  <groupId>com.baeldunggroupId>
  <version>1.0-SNAPSHOTversion>
parent>

接下来,Maven会成功生成这三个子模块。

重要的是要注意子模块只能有一个父模块。但是,我们可以导入许多 BOM。有关 BOM 文件的更多详细信息,请参阅本文。

6.3. 构建项目

现在我们可以一次构建所有三个模块。在父项目目录中,我们将运行:

mvn package

这将构建所有模块。我们应该看到该命令的以下输出:

[INFO] Scanning for projects...
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Build Order:
[INFO] parent-project                                                     [pom]
[INFO] core                                                               [jar]
[INFO] service                                                            [jar]
[INFO] webapp                                                             [war]
...
[INFO] Reactor Summary for parent-project 1.0-SNAPSHOT:
[INFO] parent-project ..................................... SUCCESS [  0.272 s]
[INFO] core ............................................... SUCCESS [  2.043 s]
[INFO] service ............................................ SUCCESS [  0.627 s]
[INFO] webapp ............................................. SUCCESS [  0.572 s]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------

Reactor 列出了 parent-project,但由于它是pom类型,因此将其排除在外,并且构建会为所有其他模块生成三个单独的.jar文件。在这种情况下,构建发生在其中三个中。

此外,Maven Reactor 将分析我们的项目并以正确的顺序构建它。因此,如果我们的webapp 模块依赖于service模块,Maven 将首先构建service,然后 构建webapp

6.3. 在父项目中启用依赖管理

依赖管理是一种为多模块父项目及其子项目集中依赖信息的机制。

当您有一组项目或模块继承了一个共同的父级时,您可以将有关依赖项的所有必需信息放在共同的pom.xml文件中。这将简化对子POM中工件的引用。

让我们看一个示例父级的pom.xml

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframeworkgroupId>
            <artifactId>spring-coreartifactId>
            <version>5.3.16version>
        dependency>
        //...
    dependencies>
dependencyManagement>

通过在 parent 中声明spring-core版本,所有依赖spring-core的子模块都可以只使用groupIdartifactId声明依赖,并且版本将被继承:

<dependencies>
    <dependency>
        <groupId>org.springframeworkgroupId>
        <artifactId>spring-coreartifactId>
    dependency>
    //...
dependencies>

此外,您可以在父模块的pom.xml中为依赖管理提供排除项,这样子模块就不会继承特定的库:

<exclusions>
    <exclusion>
        <groupId>org.springframeworkgroupId>
        <artifactId>spring-contextartifactId>
    exclusion>
exclusions>

最后,如果子模块需要使用不同版本的托管依赖项,您可以在子模块的pom.xml文件中覆盖托管版本:

<dependency>
    <groupId>org.springframeworkgroupId>
    <artifactId>spring-coreartifactId>
    <version>4.3.30.RELEASEversion>
dependency>

请注意,虽然子模块从其父项目继承,但父项目不一定具有聚合的任何模块。另一方面,父项目也可以聚合不继承自它的项目。

有关继承和聚合的更多信息,请参阅此文档。

6.4. 更新子模块并构建项目

我们可以更改每个子模块的封装类型。例如,让我们通过更新pom.xml文件将webapp模块的打包方式更改为WAR :

<packaging>warpackaging>

并在插件列表中添加maven-war-plugin :

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.pluginsgroupId>
            <artifactId>maven-war-pluginartifactId>
            <version>3.3.2version>
            <configuration>
               <failOnMissingWebXml>falsefailOnMissingWebXml>
            configuration>
        plugin>
    plugins>
build>

现在我们可以使用mvn clean install命令测试我们项目的构建。Maven 日志的输出应该类似于:

[INFO] Scanning for projects...
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Build Order:
[INFO] 
[INFO] parent-project                                                     [pom]
[INFO] core                                                               [jar]
[INFO] service                                                            [jar]
[INFO] webapp                                                             [war]
//............. 
[INFO] Reactor Summary for parent-project 1.0-SNAPSHOT:
[INFO] 
[INFO] parent-project ..................................... SUCCESS [  0.272 s]
[INFO] core ............................................... SUCCESS [  2.043 s]
[INFO] service ............................................ SUCCESS [  0.627 s]
[INFO] webapp ............................................. SUCCESS [  1.047 s]

7. 结论

在本文中,我们讨论了使用 Maven 多模块的好处。我们还区分了常规 Maven 的父 POM 和聚合 POM。最后,我们探讨了如何设置一个简单的多模块来开始使用。

Maven 是一个很棒的工具,但它本身就很复杂。如果我们想了解更多关于 Maven 的详细信息,可以查看Sonatype Maven 参考 或Apache Maven 指南。如果我们寻求 Maven 多模块设置的高级用法,我们可以看看Spring Boot 项目如何利用它的用法。

本文中使用的所有代码示例都可以通过 Github 获得。

你可能感兴趣的:(maven,java,intellij-idea)