七的博客

快速上手Maven(五)-多模块管理

Maven

快速上手Maven(五)-多模块管理

在实际项目开发过程中 , 一个大型项目通常会被分割成多个子模块 , 每个模块负责一部分功能。这样可以让开发结构更加清晰,同时也更加方便模块复用等。

Maven 多模块示例

使用 Maven 可以很方便地管理多模块项目,而且如果你需要自己去维护模块,比如新增、删除等,你就需要对多模块有所了解。

1. 什么是 Maven 模块

模块 ( Module )其实并不是 Maven 自己创建出来的业务术语,在计算机领域内很早以前就有这个说法。在软件工程中,模块化试一个基本原则,目的都是在提升可维护性、扩展性以及代码复用。

举个生活中比较生动形象的例子就是一台台式电脑。想象一下你在组装一台电脑,电脑可以分成很多部件,比如主板、硬盘、显卡等。通过这一个组件拼装起来,组成了一台完成的台式电脑。 在 Maven 中,每个部件就像是一个模块,每个模块负责完成特定的功能。

在 Maven 的大项目中,每个模块都能独立编写和测试。最终会被组合起来,共同构成完整的应用程序。

2. 单模块以及多模块

2.1 单模块

单模块其实就是针对单个模块的 Maven 项目,通常只有一个 pom.xml 文件,其中包含了所有的依赖、插件配置和其他构建设置。

比如第一章节我们新建的 Hello World 项目就是个单模块项目:

单模块项目结构

单模块项目结构简单,便于理解和维护,特别是对于小型或不太复杂的项目。如果强行将一个简单的项目拆分成多个模块的话,会增加不必要的工作量。

单模块随着项目规模的增长,可能变得难以管理和维护,这一点在项目规划初期就应该考虑好。 如果项目周期短,并且不存在后续迭代维护的话,直接单模块即可。

2.2 多模块

多模块样例

多模块项目是指主项目下包含多个子项目( 也称为模块 ),每个模块都是一个独立的项目,但它们共同构成了整个系统的一部分。

多模块主项目的 pom.xml 文件的打包类型需要设置为 pom,然后再文件中使用 <modules> 标签列出所有子模块。然后每个子模块有自己的 pom.xml

因为模块是分离的,每个模块负责特定的功能,所以多模块提高了代码的可读性和可维护性。同时模块可以设计成重用的,在团队协作时,可以降低开发成本和时间。

3. 多模块例子

接下来将实际创建一个多模块的例子,项目名称叫 maven-multi-module ,按照图中的序号依次创建。

多模块项目例子

3.1 创建父模块

  • 创建一个文件夹,名称为 maven-multi-module

  • 然后在该文件夹中,创建一个文件 pom.xml,编辑内容如下:

  <?xml version="1.0" encoding="UTF-8"?>
  <project xmlns="http://maven.apache.org/POM/4.0.0"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
      <modelVersion>4.0.0</modelVersion>
  
      <groupId>com.suny.maven</groupId>
      <artifactId>maven-multi-module</artifactId>
      <version>1.0-SNAPSHOT</version>
      <packaging>pom</packaging> // 注意这个
      <modules>
    
      </modules>
  
      <properties>
          <maven.compiler.source>8</maven.compiler.source>
          <maven.compiler.target>8</maven.compiler.target>
          <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
      </properties>
  
  </project>

注意打包类型为 pom , 这个很重要。

3.2 创建子模块 a

  • 在文件夹 maven-multi-module 中新建一个文件夹 module-a

  • 然后在 module-a 文件夹中,创建一个文件 pom.xml,编辑内容如下:

  <?xml version="1.0" encoding="UTF-8"?>
  <project xmlns="http://maven.apache.org/POM/4.0.0"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
      <modelVersion>4.0.0</modelVersion>
      <parent>
          <groupId>com.suny.maven</groupId>
          <artifactId>maven-multi-module</artifactId>
          <version>1.0-SNAPSHOT</version>
      </parent>
  
      <artifactId>module-a</artifactId>
      <packaging>jar</packaging>
  
      <properties>
          <maven.compiler.source>8</maven.compiler.source>
          <maven.compiler.target>8</maven.compiler.target>
          <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
      </properties>
  
  </project>

注意这个模块的打包类型为 jar ,同时使用 <parent></parent> 标签指定了父模块的坐标。这样子模块就会继承父项目的配置。

3.3 创建子模块 b

  • 在文件夹 maven-multi-module 中新建一个文件夹 module-b

  • 然后在 module-b 文件夹中,创建一个文件 pom.xml,编辑内容如下:

  <?xml version="1.0" encoding="UTF-8"?>
  <project xmlns="http://maven.apache.org/POM/4.0.0"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
      <modelVersion>4.0.0</modelVersion>
      <parent>
          <groupId>com.suny.maven</groupId>
          <artifactId>maven-multi-module</artifactId>
          <version>1.0-SNAPSHOT</version>
      </parent>
  
      <artifactId>module-b</artifactId>
      <packaging>jar</packaging>
  
      <properties>
          <maven.compiler.source>8</maven.compiler.source>
          <maven.compiler.target>8</maven.compiler.target>
          <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
      </properties>
  
  </project>

3.3 创建子模块 c

  • 在文件夹 maven-multi-module 中新建一个文件夹 module-b

  • 然后在 module-b 文件夹中,创建一个文件 pom.xml,编辑内容如下:

  <?xml version="1.0" encoding="UTF-8"?>
  <project xmlns="http://maven.apache.org/POM/4.0.0"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
      <modelVersion>4.0.0</modelVersion>
      <parent>
          <groupId>com.suny.maven</groupId>
          <artifactId>maven-multi-module</artifactId>
          <version>1.0-SNAPSHOT</version>
      </parent>
  
      <artifactId>module-c</artifactId>
      <packaging>jar</packaging>
  
      <properties>
          <maven.compiler.source>8</maven.compiler.source>
          <maven.compiler.target>8</maven.compiler.target>
          <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
      </properties>
  
  </project>

3.4 在父模块中配置子模块

修改 maven-multi-module 文件夹下的 pom.xml 内容:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.suny.maven</groupId>
    <artifactId>maven-multi-module</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>pom</packaging>
    <modules>
        <!--  增加这三个子模块 -->
        <module>module-a</module>
        <module>module-b</module>
        <module>module-c</module>
    </modules>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

</project>

3.5 打包测试

当我们在父项目的目录下运行 Maven 命令时 , 命令会递归地应用到所有的子模块。这样我们就可以用一条命令构建整个多模块项目,非常方便。

例如运行 mvn clean install 会依次在每个子模块中执行 cleaninstall 阶段。

这里我们直接在父模块目录下执行打包命令:

mvn package 

可以看到控制台输出如下 :

[INFO] Scanning for projects...
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Build Order:
[INFO]
[INFO] maven-multi-module                                                 [pom]
[INFO] module-a                                                           [jar]
[INFO] module-b                                                           [jar]
[INFO] module-c                                                           [jar]
[INFO]
[INFO] -----------------< com.suny.maven:maven-multi-module >------------------
[INFO] Building maven-multi-module 1.0-SNAPSHOT                           [1/4]
[INFO] --------------------------------[ pom ]---------------------------------
[INFO]
[INFO] ----------------------< com.suny.maven:module-a >-----------------------
[INFO] Building module-a 1.0-SNAPSHOT                                     [2/4]
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ module-a ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 0 resource
[INFO]
[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ module-a ---
[INFO] Nothing to compile - all classes are up to date
[INFO]
[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ module-a ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO]
[INFO] --- maven-compiler-plugin:3.1:testCompile (default-testCompile) @ module-a ---
[INFO] Nothing to compile - all classes are up to date
[INFO]
[INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ module-a ---
[INFO] No tests to run.
[INFO]
[INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ module-a ---
[INFO]
[INFO] ----------------------< com.suny.maven:module-b >-----------------------
[INFO] Building module-b 1.0-SNAPSHOT                                     [3/4]
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ module-b ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 0 resource
[INFO]
[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ module-b ---
[INFO] Nothing to compile - all classes are up to date
[INFO]
[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ module-b ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO]
[INFO] --- maven-compiler-plugin:3.1:testCompile (default-testCompile) @ module-b ---
[INFO] Nothing to compile - all classes are up to date
[INFO]
[INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ module-b ---
[INFO] No tests to run.
[INFO]
[INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ module-b ---
[INFO]
[INFO] ----------------------< com.suny.maven:module-c >-----------------------
[INFO] Building module-c 1.0-SNAPSHOT                                     [4/4]
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ module-c ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 0 resource
[INFO]
[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ module-c ---
[INFO] Nothing to compile - all classes are up to date
[INFO]
[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ module-c ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO]
[INFO] --- maven-compiler-plugin:3.1:testCompile (default-testCompile) @ module-c ---
[INFO] Nothing to compile - all classes are up to date
[INFO]
[INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ module-c ---
[INFO] No tests to run.
[INFO]
[INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ module-c ---
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Summary for maven-multi-module 1.0-SNAPSHOT:
[INFO]
[INFO] maven-multi-module ................................. SUCCESS [  0.005 s]
[INFO] module-a ........................................... SUCCESS [  0.550 s]
[INFO] module-b ........................................... SUCCESS [  0.054 s]
[INFO] module-c ........................................... SUCCESS [  0.053 s]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS

证明这个多模块搭建成功了,可以直接通过父模块对子模块进行聚合操作。

4. 利用父模块管理依赖版本

在多模块项目中 , 所有模块的版本通常是同步的,这样有利于管理子模块的版本号。

我们可以在父项目的 pom.xml 中定义一个版本号,然后在子模块中引用这个版本号。例如:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.suny.maven</groupId>
    <artifactId>maven-multi-module</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>pom</packaging>
    <modules>
        <!--  增加这三个子模块 -->
        <module>module-a</module>
        <module>module-b</module>
        <module>module-c</module>
    </modules>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <!--  增加一个子模块公用的版本号 -->
        <revision>1.0-SNAPSHOT</revision>
    </properties>

</project>

在子模块中直接使用 ${revision} 来替代版本号:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <groupId>com.suny.maven</groupId>
        <artifactId>maven-multi-module</artifactId>
        <version>${revision}</version>
    </parent>

    <artifactId>module-a</artifactId>
    <packaging>jar</packaging>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

</project>

这样 , 所有的子模块都可以直接继承父项目的 revision 属性 , 并使用相同的版本号。

使用 revision 的好处是是当你需要更新项目的版本时 , 你只需要在父项目的 pom.xml 文件中修改 revision 属性的值 , 所有的子模块都会自动使用新的版本号 , 不需要逐个修改。

5. 参考链接