Maven继承与聚合详解及作用介绍
作者:mzz124 发布时间:2023-03-08 00:14:36
一、继承
引言
继承关系可以对不同模块的依赖版本做统一管理,因为子模块中的依赖基本都继承于父模块,父模块中指定哪个版本,子模块就继承哪个版本,可以有效避免不同模块可能采用不同版本的依赖时产生的冲突
1. 继承关系的实现
(1)parent 模块设置
parent 模块即父模块,由于父模块只是为了给子模块提供依赖,所以父模块中只需要一个 pom.xml 文件即可。父模块的打包方式必须设置为 pom(默认打包方式是 jar)
<groupId>com.mzz</groupId>
<artifactId>parent-maven</artifactId>
<version>1.0-SNAPSHOT</version>
<!-- 设置打包方式为 pom -->
<packaging>pom</packaging>
只要设置了 packaging 属性为 pom,这个模块就可以作为 parent 模块被继承了
(2)子模块设置
子模块中只要设置了 parent 标签,就可以建立继承关系。
所以继承主要体现在子模块,parent 模块是感受不到继承关系的,也无法从 parent 模块中看出哪些模块继承了自己。
另外继承关系建议以后,如果子模块与父模块处于同一 groupId 下,那么子模块可以不写 groupId
<!--<groupId>com.mzz</groupId>-->
<artifactId>project-dao</artifactId>
<version>1.0-SNAPSHOT</version>
<parent>
<!-- parent 模块的坐标与版本 -->
<groupId>com.mzz</groupId>
<artifactId>parent-maven</artifactId>
<version>1.0-SNAPSHOT</version>
<!-- parent 模块的相对路径 -->
<relativePath>../parent-maven/pom.xml</relativePath>
</parent>
对 relativePath 属性做一些补充:
relativePath 可以省略,前提是 parent 模块已经 install 至仓库,否则子模块无法定位到 parent,不能通过编译
相对路径最后可以不写 pom.xml,只定位到父模块的文件夹也可以
2. 依赖配置
(1)必须继承的依赖
parent 模块中声明的依赖便是子模块必须继承的依赖,子模块中不必声明便从父模块中继承了这些依赖
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.20.RELEASE</version>
</dependency>
<!-- 省略了其他依赖的声明 -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope><!-- scope 属性也会被继承 -->
</dependency>
<dependencies>
如上图,可见子模块中未声明依赖就继承了 parent 中的所有依赖
(2)有选择地继承依赖
parent 模块中设置依赖管理 dependencyManagement 后,在其中声明的依赖就是供子模块选择的依赖。子模块需要哪些依赖,必须在子模块中声明依赖,但不需要注明 version,因为版本由 parent 来指定。
<!-- parent 模块 -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.2.10.RELEASE</version>
<scope>test</scope>
</dependency>
</dependencies>
</dependencyManagement>
<!-- 子模块声明依赖 -->
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
</dependency>
</dependencies>
如果子模块声明的依赖有 version 属性,那么这个依赖并不继承自 parent
另外,parent 模块声明在 dependencyManagement 中的依赖并不被 parent 模块所依赖
(3)插件继承
插件的继承规则和设置方法与前面的依赖极为相似,同样也有插件管理 pluginManagement,与 dependencyManagement 类似,这里给出一个 parent 中设置的样例模板
<build>
<plugins>
<!-- 声明必须继承的插件 -->
</plugins>
<pluginManagement>
<plugins>
<!-- 声明可供选择是否继承的插件 -->
</plugins>
</pluginManagement>
</build>
二、聚合
引言
聚合就是指将多个模块组织成一个整体,同时进行项目的构建工作。
使用聚合可以避免分模块开发时的一些问题,比如某个模块更新了一些内容,但其它已经构建好的模块不会进行更新,将所有模块聚合之后,只对聚合模块进行构建就会对所有模块都进行构建,能够及时的发现问题
实现聚合
聚合模块也被称为 root 模块,同样是一个只需要 pom.xml 文件的项目,只要设置了 modules 标签,再将聚合的模块添加进去,即可实现聚合
<modules>
<!-- module 属性中写明被聚合模块的相对路径 -->
<module>../project-pojo</module>
<module>../project-dao</module>
<module>../project-service</module>
</modules>
如上例,将 pojo,dao 和 service 三个模块进行了聚合,只要对聚合模块进行构建,这三个模块也会被一起构建
聚合只体现在聚合模块,被聚合的模块也无法感知自身被谁所聚合
三、继承与聚合的合并
继承是的 parent 模块和聚合时的 root 模块都只有 pom.xml,因为他们都是设计型模块,不包含实际的模块内容。事实上,继承与聚合经常被合并在一起使用,父模块(parent)也作为聚合模块(root)使用,只需要在父模块中加入 modules 属性,将子模块聚合即可
这时要说一说继承时说到的 relativePath 属性,前面说 relativePath 属性可以省略,前提是父模块已经构建并 install 至仓库,否则子模块无法构建,但此时父模块同时也聚合了子模块,要构建父模块就又要一起构建子模块,但构建子模块又需要父模块 install 至仓库……陷入了套娃问题
此时构建父模块 maven 会报错: Non-resolvable parent POM for XXX.XXX.XXX Could not find artifact com.mzz:parent-maven:pom:1.0-SNAPSHOT and ‘parent.relativePath’ points at wrong local POM,原因是无法定位 parent 模块
解决方法也很简单,要么老老实实在子模块中 parent 标签中加入 relativePath 属性,使 maven
可以根据相对路径找到父模块,要么,先将父模块中的 modules 注释掉,暂时不做聚合,将父模块 install 之后再取消注释,然后就能一起构建啦
来源:https://blog.csdn.net/Cey_Tao/article/details/126567296


猜你喜欢
- Java中 * 主要有JDK和CGLIB两种方式。区别主要是jdk是代理接口,而cglib是代理类。优点:这种方式已经解决我们前面所有日记
- 好几年没写博客了,很多知识不记是真的会忘记,以后还是保持写博客的习惯吧。坚持不一定成功,但放弃一定很舒服!(开玩笑(#^.^#))回归正题,
- 主从表关联查询,返回对象带有集合属性昨天有同事让我帮着看一个问题,mybatis主从表联合查询,返回的对象封装集合属性。我先将出现的问题记录
- 在2020.1.1版本之前IDEA pom文件导包是这样的最近新装新版本IDEA之后,这个图标没有了,对于习惯旧操作没有图标了还真不习惯。就
- Nacos 的部署,我使用的时docker 部署(单机模式 Mysql),官网文档:https://nacos.io/zh-cn/docs/
- 注释介绍@Cacheable@Cacheable 的作用 主要针对方法配置,能够根据方法的请求参数对其结果进行缓存@Cacheable 作用
- 前两天看了个扫雷的视频,于是自己跟着做了下,感觉还不是很难。初学Java的同学可以尝试自己操作下Java小程序这样子才能提高自己的理解能力和
- 在.Net中,对文件(File)和文件夹(Folder)的操作可以使用File类和Directory类,也可以使用FileInfo类和Dir
- 简介我们在前面的Android教程中已经提到过这么一件事:Android在启动后会有一个主线程。它不允许任何子线程去改变主UI线程里的内容。
- Java 8新增了LocalDate和LocalTime接口,为什么要搞一套全新的处理日期和时间的API?因为旧的java.util.Dat
- 前言:现在一般的Android软件都是需要不断更新的,当你打开某个app的时候,如果有新的版本,它会提示你有新版本需要更新。当有更新时,会弹
- Logger来自log4j自己的包。如果用Logger.getLogger,需要一个log4j的jar包,用此方式你只能依log4j:Log
- 目录1、在异常处理中,如释放资源,关闭数据库、关闭文件应由( )语句来完成。2、如下Java语句 double x=2.0; int y=4
- 本文实例讲述了Android编程实现动态支持多语言的方法。分享给大家供大家参考,具体如下:资源文件values/strings.xml中添加
- 传统的多分支方式(圈复杂度为6):public String order(String type) { if ("1&
- C#实现IDispose接口.net的GC机制有两个问题:首先GC并不能释放所有资源,它更不能释放非托管资源。其次,GC也不是实时的,所有G
- Unity中的PostProcessBuild:深入解析与实用案例在Unity游戏开发中,我们经常需要在构建完成后对生成的应用程序进行一些额
- 用 Android studio软件写的一个 * 小游戏先上MainActivity.java 的代码。这里我用得定时器,本想用j
- 什么是OKHttp一般在Java平台上,我们会使用Apache HttpClient作为Http客户端,用于发送 HTTP 请求,并对响应进
- 本文实例讲述了C#使用WebService结合jQuery实现无刷新翻页的方法。分享给大家供大家参考。具体如下:1. 首先创建数据库、表Ar