快速上手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
会依次在每个子模块中执行 clean
和 install
阶段。
这里我们直接在父模块目录下执行打包命令:
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. 参考链接
- Introduction to the POM https://maven.apache.org/guides/introduction/introduction-to-the-pom.html