maven聚合工程详解

news2024/11/28 14:37:53

目录

    • 一、Maven继承
    • 二、idea搭建父子工程
    • 三、可继承的 POM 元素
    • 四、Maven聚合
    • 五、idea搭建聚合工程
    • 六、继承和聚合的关系
    • 七、dependencyManagement
    • 八、pluginManagement

本篇文章重点针对这几个问题进行讲解:

  1. Maven继承
  2. 使用IDEA搭建Maven父子工程
  3. 使用IDEA搭建Maven聚合工程
  4. Maven父子工程和聚合工程的区别

一、Maven继承

Maven 在设计时,借鉴了 Java 面向对象中的继承思想,提出了 POM 继承思想。

当一个项目包含多个模块时,可以在该项目中再创建一个父模块,并在其 POM 中声明依赖,其他模块的 POM 可通过继承父模块的 POM 来获得对相关依赖的声明。对于父模块而言,其目的是为了消除子模块 POM 中的重复配置,其中不包含有任何实际代码,因此父模块 POM 的打包类型(packaging)必须是 pom

继承所涉及到的标签如下:

在这里插入图片描述

二、idea搭建父子工程

1.新建父工程,这里就正常选择springboot就可以

2.idea会让你选择需要引入的框架,这里我们直接下一步就可以

3.删除无用文件

4.将pom.xml的packaging标签改为pom

新建springboot项目默认继承了spring-boot-starter-parent,spring-boot-starter-parent当中给我们提供了大量的配置,很多框架的版本号都有,而我们在继承过后很多框架就不需要声明版本号了,既然是官方提供的,那也就不用担心框架与框架版本不适配的问题了。

这里为了做父子依赖继承的测试,我引用了一个lang3的包,完整的依赖如下:

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.7.10</version>
		<relativePath/>
		<!-- lookup parent from repository -->
	</parent>
	<groupId>com.gzl.cn</groupId>
	<artifactId>paren-demo</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>paren-demo</name>
	<description>paren-demo</description>
	<packaging>pom</packaging>
	<properties>
		<java.version>1.8</java.version>
	</properties>
	<!--依赖管理-->
	<dependencyManagement>
		<dependencies>
			<dependency>
				<groupId>cn.hutool</groupId>
				<artifactId>hutool-all</artifactId>
				<version>5.8.18</version>
			</dependency>
		</dependencies>
	</dependencyManagement>

	<dependencies>
		<dependency>
			<groupId>org.apache.commons</groupId>
			<artifactId>commons-lang3</artifactId>
			<version>3.12.0</version>
		</dependency>
	</dependencies>

</project>

5.新建子项目

这里<relativePath/>的尽量去掉,不然可能会报异常!子模块的 POM 中,当前模块的 groupId 和 version 元素可以省略,但这并不意味着当前模块没有 groupId 和 version,子模块会隐式的从父模块中继承这两个元素,即由父模块控制子模块的公司组织 id 以及版本,这样可以简化 POM 的配置。

6.现在存在一个问题,项目没有被idea识别成maven项目
(1)首先点击工具栏最左边的 Help 再点击 Find Action ;或者使用快捷键 Ctrl+Shift+A
(2)接着在输入框中输入 maven projects ,会弹出一个 Add Maven Projects 选项,点击即可,会弹出下图的弹窗

(3)最后,选择本项目的 pom.xml 点击 OK 即可解决!

观察如下:

三、可继承的 POM 元素

四、Maven聚合

上面项目只是新建了一个子项目,在实际的开发过程中,我们所接触的项目一般都由多个模块组成。在构建项目时,如果每次都按模块一个一个地进行构建会十分得麻烦,Maven 的聚合功能很好的解决了这个问题。

使用 Maven 聚合功能对项目进行构建时,需要在该项目中额外创建一个的聚合模块,然后通过这个模块构建整个项目的所有模块。聚合模块仅仅是帮助聚合其他模块的工具,其本身并无任何实质内容,因此聚合模块中只有一个 POM 文件,不像其他的模块一样包含 src/main/java、src/test/java 等多个目录。

与父模块相似,聚合模块的打包方式(packaging)也是 pom,用户可以在其 POM 中通过 modules 下的 module 子元素来添加需要聚合的模块的目录路径。

<modules>
	<module>user-service</module>
</modules>

五、idea搭建聚合工程

还是拿上面的项目作为示例,这是没有聚合前的样子:paren-demo和user-service是同级的

修改 Root 模块 POM 的配置如下:

这时候对父工程进行clean install的时候会发现,他会连带着子工程一块进行构建

聚合模块在构建时,Maven 会先解析聚合模块的 POM、分析需要构建的模块,并根据这些模块之间的关系计算出构建顺序,然后根据这个顺序依次构建各个模块。

构建完成后输出的是一个项目构建的小结报告,该报告中包括各个模块构建成功与否、构建花费的时间、以及整个构建构成所花费的时间等信息。

六、继承和聚合的关系

Maven 的继承和聚合的目的不同,继承的目的是为了消除 POM 中的重复配置,聚合的目的是为了方便快速的构建项目。

  • 对于继承中的父模块来说,它跟本不知道那些模块继承了它,但子模块都知道自己的父模块是谁。
  • 对于聚合模块来说,它知道哪些模块被聚合了,但那些被聚合的模块根本不知道聚合模块的存在。

两者在结构和形式上还是有一定的共同点的,最直观的就是两者的打包方式都是 pom,两者除了 POM 外都没有实际的代码内容。

注意:没有继承照样可以使用聚合,没有聚合照样也可以使用继承,两个之间并没有依赖关系!

在实际开发当中一般都是聚合和继承一块使用的,使用idea可以快速的创建,如下:

虽然使用这种方式创建maven项目可以帮我们省去修改pom的时间,但是我们还需要手动修改springboot启动类,以及添加resources文件夹。

七、dependencyManagement

我们知道,子模块可以通过继承获得父模块中声明的全部依赖,这样虽然避免了在各个子模块 POM 中重复进行依赖声明,但也极有可能造成子模块中引入一些不必要的依赖。为此 Maven 引入了 dependencyManagement 来对依赖进行管理。

Maven 可以通过 dependencyManagement 元素对依赖进行管理,它具有以下 2 大特性:

  • 在该元素下声明的依赖不会实际引入到模块中,只有在 dependencies 元素下同样声明了该依赖,才会引入到模块中。
  • 该元素能够约束 dependencies 下依赖的使用,即 dependencies 声明的依赖若未指定版本,则使用 dependencyManagement 中指定的版本,否则将覆盖 dependencyManagement 中的版本。

在实际的开发过程中,dependencyManagement 很少会单独使用,通常它需要与 Maven 继承或依赖范围 import 配合使用才能展现它的优势。

比如在父依赖当中使用如下pom:

<dependencyManagement>
	<dependencies>
		<dependency>
			<groupId>cn.hutool</groupId>
			<artifactId>hutool-all</artifactId>
			<version>5.8.18</version>
		</dependency>
	</dependencies>
</dependencyManagement>

这时候子模块就可以只通过groupId和artifactId来引入框架了。可以省去了 version 和 scope。

<dependencies>
	<dependency>
		<groupId>cn.hutool</groupId>
		<artifactId>hutool-all</artifactId>
	</dependency>
</dependencies>

使用这种依赖管理机制似乎并不能减少太多 POM 配置,但我们仍然推荐使用这种方式,其原因主要有 2 个:

  • 在父模块中使用 dependencyManagement声明依赖能够统一项目内依赖的版本,子模块无须声明版本,也就不会出现多个子模块使用同一依赖项版本不一致的情况,降低依赖冲突的几率。
  • dependencyManagement 声明的依赖不会被实际引入,子模块需要什么依赖就自己引入,增加了灵活性,避免引入一些不必要的依赖

import 依赖范围只能与 dependencyManagement 元素配合使用才会有效,其功能是将目标 pom.xml 中的 dependencyManagement 配置导入合并到当前 pom.xml 的 dependencyManagement 中。

关于spring-boot-dependencies不是很了解的可以看一下这篇文章:https://blog.csdn.net/weixin_43888891/article/details/130520345

<dependencyManagement>
	 <dependencies>
		<dependency>
			 <groupId>org.springframework.boot</groupId>
			 <artifactId>spring-boot-dependencies</artifactId>
			 <version>2.7.10</version>
			 <type>pom</type>
			 <scope>import</scope>
		 </dependency>
	</dependencies>
</dependencyManagement>

以上配置中,由于 import 依赖范围的特殊性,一般都是指向打包类型为 pom 的模块,所以 type 元素的值一般为 pom。

例如spring-boot-dependencies当中有很多dependencyManagement管理的项目,他会将dependencyManagement当中所有依赖管理导入到当前项目。

八、pluginManagement

pluginManagement 元素与 dependencyManagement 元素的原理十分相似,在 pluginManagement 元素中可以声明插件及插件配置,但不会发生实际的插件调用行为,只有在 POM 中配置了真正的 plugin 元素,且其 groupId 和 artifactId 与 pluginManagement 元素中配置的插件匹配时,pluginManagement 元素的配置才会影响到实际的插件行为。

当项目中的多个模块存在相同的插件时,应当将插件配置移动到父模块的 pluginManagement 元素中。即使各个模块对于同一插件的具体配置不尽相同,也应当在父模块中使用 pluginManagement 元素对插件版本进行统一声明。

在spring-boot-dependencies给我们提供了大量的插件版本管理,这也就是我们在springboot项目当中引用插件有时候根本不需要声明版本号的原因:

springboot父pom默认配置如下:

  • delimiter:就是更改变量取值的形式,上面也有提到过。
  • propertiesEncoding:就是字符编码

然后我又在自己的项目当中声明了maven-resources-plugin插件:

<plugin>
	<groupId>org.apache.maven.plugins</groupId>
	<artifactId>maven-resources-plugin</artifactId>
	<version>3.2.0</version>
	<configuration>
	  <nonFilteredFileExtensions>
		 <!--不应用过滤的其他文件扩展名(已定义的有:jpg, jpeg, gif, bmp, png)-->
		  <nonFilteredFileExtension>xls</nonFilteredFileExtension>
		  <nonFilteredFileExtension>xlsx</nonFilteredFileExtension>
	   </nonFilteredFileExtensions>
	</configuration>
</plugin>

这里有一点需要注意,springboot在父pom的pluginManagement设置了maven-resources-plugin,而我们又在项目当中声明了maven-resources-plugin,最终他生效的是父pom+我们声明的配置:

通过mvn help:effective-pom命令即可查看生效的pom

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/550761.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【建议收藏】Python自动化必不可少的测试框架 — pytest

每天进步一点点&#xff0c;关注我哦&#xff0c;每天分享测试技术文章 Python在测试圈的应用非常广泛&#xff0c;特别是在自动化测试以及测试开发的领域&#xff0c;其中在自动化测试中我们常用的测试框架是uniitest和pytest&#xff0c;本文将带领大家搭建以及熟悉pytest的使…

改进YOLOv5系列:ResNeXt融合特征金字塔,引领YOLOv5目标检测

目录 一、介绍1、YOLOv5简介2、ResNeXt简介3、目标检测简介 二、YOLOv5及其局限性1、YOLOv5的架构与原理2、YOLOv5的优势3、YOLOv5的局限性 三、ResNeXt与特征金字塔融合1、ResNeXt的基本原理2、ResNeXt的优势3、特征金字塔的基本原理4、特征金字塔的优势5、ResNeXt与特征金字塔…

mysql JDBC的三种查询(普通、流式、游标)

使用JDBC向mysql发送查询时&#xff0c;有三种方式&#xff1a; 常规查询&#xff1a;JDBC驱动会阻塞的一次性读取全部查询的数据到 JVM 内存中&#xff0c;或者分页读取流式查询&#xff1a;每次执行rs.next时会判断数据是否需要从mysql服务器获取&#xff0c;如果需要触发读…

找计算机研究的论文18个平台

虽然说目前arvix是计算机领域跟进最新研究成果论文的网站&#xff0c;有时候我们也需要找一些其他的好论文&#xff0c;比如一个很久之前的。我们整理了18个相关平台&#xff0c;包括几个可以免费下载和阅读CS相关技术论文的网站&#xff0c;收录到 找计算机研究的论文18个平台…

secure CRT 常见问题配置

文章目录 颜色主题如何切换 SecureCRT 颜色主题如何新建SecureCRT 颜色 主题如何拷贝我的颜色主题,主题名为pic 系统间拷贝基于clipboard的文字shell下的VIM系统间拷贝1. 确保 ubuntu 上的 vim 支持 clipboard 特性2. 确保 图形shell下的 vim(gvim) 支持 系统间拷贝3. 确保 文字…

004 - STM32固件库GPIO(三)位带操作

目前掌握的对GPIO引脚的输入输出操作只能使用BSRRL/H、I/ODR寄存器&#xff0c;记得以前学51的时候&#xff0c;对于引脚的输入输出可以采用关键字sbit实现位定义,例如 sbit LED1 P1^3;在STM32中没有类似于sbit一样的关键字&#xff0c;但是提供了位带操作来实现类似于51的为…

ARM的状态传送器指令、软中断指令与协处理指令(软中断具体实现)

1.状态寄存器传送指令: 作用&#xff1a;访问&#xff08;读写&#xff09;CPSR寄存器 CPSR寄存器结构图&#xff1a; 前八位的作用&#xff1a; Bit[4:0] &#xff1a;不同的电平组合表示不同的模式&#xff0c;[10000]User [10001]FIQ [10010]IRQ [10011]SVC …

【Hadoop】二、Hadoop MapReduce与Hadoop YARN

文章目录 二、Hadoop MapReduce与Hadoop YARN1、Hadoop MapReduce1.1、理解MapReduce思想1.2、Hadoop MapReduce设计构思1.3、Hadoop MapReduce介绍1.4、Hadoop MapReduce官方示例1.5、Map阶段执行流程1.6、Reduce阶段执行流程1.7、Shuffle机制 2、Hadoop YARN2.1、Hadoop YARN…

导入源码至Android Studio

导入源码至Android Studio 参考&#xff1a; Android源码环境搭建&#xff08;aosp Ubuntu 16.04&#xff09; 使用如下的步骤&#xff1a; 1.. build/envsetup.sh (source可以用 .代替&#xff0c;即". build/envsetup.sh") 2.lunch&#xff0c;并选择要编译的项…

jmeter请求Sse长链接接口

文章目录 1.背景1.1 什么是SSE接口 2. **解决思路-尝试方法⬇️&#xff1a;**2.1 &#x1f3f3;️‍&#x1f308; **postman-sse请求结果**2.2 **⚡ jmeter报错**2.3 ☀️**封装此SSE接口**2.3.1 ❌httpclient2.3.2 ❌HttpURLConnection2.3.3 ✔️okhttp3 3. jmeter-beanshel…

跟我一起使用 compose 做一个跨平台的黑白棋游戏(3)状态与游戏控制逻辑

前言 在上一篇文章中&#xff0c;我们已经完成了黑白棋的界面设计与编写&#xff0c;今天这篇文章我们将完成状态控制和游戏逻辑代码的编写。 正如第一篇文章所述&#xff0c;在本项目中&#xff0c;我们需要实现不依赖于平台的状态管理&#xff0c;也就是使用 Flow 和 compo…

浏览器扩展一些好用插件

给浏览器添加一些插件功能&#xff0c;能够让我们用的更方便&#xff0c;开发中非常实用&#xff0c;下面直接开始 我们这里选择的是微软自带的Microsoft Edge浏览器&#xff08;谷歌也行。这两款浏览器都是非常好用的&#xff09; 我们打开浏览器找到扩展应用这个&#xff0c;…

opencv 中值滤波

中值滤波是一种常用的图像滤波算法&#xff0c;是在像素点周围进行多个点的中值滤波&#xff0c;将点的灰度值根据其周围像素点的灰度值进行平均&#xff0c;并使这些点的灰度值具有相似性&#xff0c;以达到平滑去噪的目的。中值滤波在图像处理中应用广泛&#xff0c;在图像滤…

利用java编写的项目设备调配系统代码示例(内含5种设备调配的算法)

利用java编写的项目设备调配系统代码示例&#xff08;内含5种设备调配的算法&#xff09; 一、设备调配方案二、设备匹配算法三、代码实现&#xff08;java&#xff09; 最近在做一个项目设备调配系统&#xff0c;分享一些干货&#xff01;&#xff01;&#xff01; 一、设备…

Godot引擎 4.0 文档 - 入门介绍 - Godot 关键概念概述¶

本文为Google Translate英译中结果&#xff0c;DrGraph在此基础上加了一些校正。英文原版页面&#xff1a;Overview of Godots key concepts — Godot Engine (stable) documentation in English Godot 关键概念概述 每个游戏引擎都围绕您用来构建应用程序的抽象展开。在 Godo…

【mysql】库的操作+表的操作

文章目录 启动mysql登录mysql1.MySQL环境安装与基础认识修改端口号连接服务器服务器&#xff0c;数据库&#xff0c;表关系建表 第二讲_库与表的操作1.创建数据库2.创建数据库案例3.指明字符集和校验集校验规则对数据库的影响不区分大小写的查询以及结果&#xff1a;区分大小写…

SQL Backup Master 6.3.6 Crack

SQL Backup Master 能够为用户将 SQL Server 数据库备份到一些简单的云存储服务中&#xff0c;例如 Dropbox、OneDrive、Amazon S3、Microsoft Azure、box&#xff0c;最后是 Google Drive。它能够将数据库备份到用户和开发者的FTP服务器上&#xff0c;甚至本地机器甚至网络服务…

速通二次型、二次型标准型、二次型规范型

浅过二次型 理解二次型可以从二次型的多项式入手&#xff1a; 显然&#xff0c;在系数都为实数的情况下&#xff0c;二次型矩阵即为一个实对称矩阵。 取一个代入值的例子就是&#xff1a; 二次型的标准型 OK&#xff0c;再从二次型的标准型的多项式入手&#xff0c;如下&…

FPGA System Planner(FSP)使用手册

FSP工具是cadence公司为了FPGA/PCB协同设计而推出的一个解决方案工具包。它的主要工作是由软件来自动生成、优化FPGA芯片的管脚分配,提高FPGA/PCB设计的工作效率和连通性。FSP完成两顷重要工作:一、可以自动生成FPGA芯片的原理图符号(symbol);二、自动生成、优化和更改FPG…

C++模板(上)

文章目录 模板函数模板函数模板的实例化 类模板总结 模板 模板是C种为了方便用户对于一些场景的使用&#xff0c;引入的新概念&#xff0c;使得我们的代码不会冗余 template关键字 template关键字的意思就是模板&#xff0c;语法为&#xff1a;template<typename T1,type…