# 概念
Maven 之间,A 工程继承 B 工程
B 工程:父工程
A 工程:子工程
本质上是 A 工程的 pom.xml 中的配置继承了 B 工程中 pom.xml 的配置
# 作用
在父工程中统一管理项目中的依赖信息,具体来说是 <font color='red'> 管理依赖信息的版本 </font>
它的背景是:
对一个比较大型的项目进行了模块拆分
一个 project 下面,创建了很多个 module
每个 module 都需要配置自己的依赖信息
它背后的需求是:
在每一个 module 中各自维护各自的依赖信息很容易发生出入,不易统一管理
使用同一个框架内的不同 jar 包,它们应该是同一个版本,所以整个项目中使用的框架版本需要统一
使用框架时所需要的 jar 包组合 (或者说依赖信息组合) 需要经过长期摸索和反复调式,最终确定一个可用组合,这个耗费很大精力总结出来的方案不应该在新的项目中重新摸索
通过父工程中为整个项目维护依赖信息的组合即 <font color='blue'> 保证了整个项目使用规范,准确的 jar 包 </font>; 又能够将 < font color='blue'> 以往的经验沉淀 </font > 下来,节约时间和精力
# 操作
<font size=4> 创建父工程 </font>
创建的过程和前面创建 pro01-maven-java 一样
工程名:pro03-maven-parent
工程创建好之后,要修改它的打包方式:
<groupId>com.dkx.maven</groupId> | |
<artifactId>pro03-maven-parent</artifactId> | |
<version>1.0-SNAPSHOT</version> | |
<!-- 当前工程作为父工程,它要去管理子工程,所以打包方式必须是 pom --> | |
<packaging>pom</packaging> |
只有打包为 pom 的 Maven 工程能够管理其它 Maven 工程,打包方式为 pom 的 Maven 工程中不写业务代码,它是专门管理其它 Maven 工程的工程
# 创建模块工程
模块工程类似于 IDEA 中的 module, 所以需要进入 <font color='blue'>pro03-maven-parent</font > 工程的根目录,然后运行 mvn archetype:generate
命令来创建模块工程
假设,我们创建三个模块工程
# 查看被添加新内容的父工程 pom.xml
下面 modules 和 module 标签是聚合功能的配置
<modules> | |
<module>pro04-maven-module</module> | |
<module>pro05-maven-module</module> | |
<module>pro06-maven-module</module> | |
</modules> |
子工程中导入父工程相同的标签可以省略不写
<!-- 导入父工程 --> | |
<parent> | |
<groupId>com.dkx.maven</groupId> | |
<artifactId>pro03-maven-parent</artifactId> | |
<version>1.0-SNAPSHOT</version> | |
</parent> | |
<!-- 子工程中与父工程相同内容的标签可以省略不写 --> | |
<!--<groupId>com.dkx.maven</groupId>--> | |
<artifactId>pro04-maven-module</artifactId> | |
<!--<version>1.0-SNAPSHOT</version>--> |
导入依赖可以省略不写版本号可以由父工程来提供统一的版本号除非特殊情况可自己指定
- 子工程
<dependencies> | |
<dependency> | |
<groupId>junit</groupId> | |
<artifactId>junit</artifactId> | |
<version>3.8.1</version> | |
<scope>test</scope> | |
</dependency> | |
<!-- 即使在父工程配置了对依赖的管理,子工程需要使用具体哪一个依赖还是要明确配置 --> | |
<dependency> | |
<groupId>org.springframework</groupId> | |
<artifactId>spring-core</artifactId> | |
<!-- 对于已经在父工程进行了管理的依赖,子工程中引用时可以不写 vserion --> | |
<!--<version>4.0.0.RELEASE</version>--> | |
<!-- 情况 1 省略 vserion: 子工程采纳的就是父工程管理的版本 --> | |
<!-- 情况 2 没有省略 vserion: 和父工程管理的版本一致,最终采纳还是这个版本,多此一举 | |
另情:配置 version 但是和父工程的版本不一致,那么子工程配置的版本会覆盖父工程的版本最终采纳子工程的版本 | |
--> | |
</dependency> | |
</dependencies> |
- 父工程:需要使用标签 <dependencyManagement> 将 < dependencies > 包裹起来
<dependencyManagement>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.0.0.RELEASE</version>
</dependency>
</dependencies>
</dependencyManagement>
一处更改全部执行:将父工程的版本号修改子工程也全部会随即修改
将版本号在父工程中全部修改为 6.0.3
执行命令查看子工程的版本号是否被自动修改
# 自定义标签统一管理 vsersion
创建自己定义的属性标签来进行统一版本且可以动态更换
在标签 properties 中定义我们自己自定义的一个标签,然后使用表达式的格式来引用
- 定义标签
<properties> | |
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> | |
<!-- 我们自定义属性标签 --> | |
<!-- 标签名:属性名 --> | |
<!-- 标签值:属性名 --> | |
<!-- 引用方式:${dkx} --> | |
<dkx>6.0.3</dkx> | |
</properties> |
- 引用标签
<dependency> | |
<groupId>org.springframework</groupId> | |
<artifactId>spring-core</artifactId> | |
<!-- 通过引用属性表达式设定版本号,这样版本号就成了一个动态值 --> | |
<version>${dkx}</version> | |
</dependency> |
执行结果:
# 实际意义
编写一套符合要求,开发各种功能都能正常工作的依赖组合并不容易,如果公司里已经有人总结了成熟的组合方案,那么再开发新项目时,如果不使用原有的积累,而是重新摸索,会浪费大量的时间,为了提高效率,我们可以使用工程继承的机制,让成熟的依赖组合方案能够保留下来
如上图所示,公司级的父工程中管理的就是成熟的依赖组合方案,各个新项目,子系统各取所需即可
# Maven 中的聚合
使用一个 "总工程" 将各个 "模块工程" 汇集起来,作为一个整体对应完整的项目
项目:整体
模块:部分
概念的对应关系:
从继承关系角度看:
父工程
子工程
从聚合关系角度看:
总工程
模块工程
# 好处
- 一键执行 Maven 命令:很多构建命令都可以在 "总工程" 中一键执行
以 mvn install 命令为例:Maven 要求有父工程时先安装父工程;有依赖的工程时,先安装被依赖的工程,我们考虑这些规则会很麻烦,但是工程聚合之后,在总工程执行 mvn install 可以一键完成安装,而且会自动按照正确的顺序执行
- 配置聚合之后,各个模块工程会在总工程中展示一个列表,让项目中的各个模块一目了然
# 聚合的配置
在总工程中配置 modules
即可:
<modules> | |
<module>pro04-maven-module</module> | |
<module>pro05-maven-module</module> | |
<module>pro06-maven-module</module> | |
</modules> |
# 依赖循环问题
如果 A 工程依赖 B 工程,B 工程依赖 C 工程,C 工程又反过来依赖 A 工程,那么在执行构建操作时会报下面错误: