邯郸哪里做网站优化/启信聚客通网络营销策划
文章目录
- 1.前言
- 2.模块的继承
- 2.1.可继承的标签
- 2.2.超级POM
- 2.3.手动引入自定义父POM
- 3.模块的聚合
- 3.1.聚合的注意事项
- 3.2.反应堆(reactor)
- 4.依赖管理及属性配置
- 4.1.依赖管理
- 4.2.属性配置
- 5.总结
1.前言
本系列文章记录了 Maven 从0开始到实战的过程,Maven 系列历史文章清单:
(一)5分钟做完 Maven 的安装与配置
(二)使用 Maven 创建并运行项目、聊聊 POM 中的坐标与版本号的规则
(三)Maven仓库概念及私服安装与使用 附:Nexus安装包下载地址
(四)图解Maven3依赖的功能特性:依赖范围、依赖传递、依赖冲突
在前面4章的内容中,我们已经知道了怎么从0开始搭建Maven环境、Maven仓库,以及使用Maven来组织和构建简单的项目,本篇会继续在这基础上扩展,讲解Maven的继承与聚合的特性,并通过这样的特性来组织构建多模块的项目。
本篇将会通过一个简单的多模块Demo项目来展开,主要的内容包括:
- 继承的概念与使用,超级POM介绍
- 模块聚合使用上的约定
- 通过反应堆自定义模块是否构建与构建顺序
2.模块的继承
在Java中,继承的作用,往往是为了子类能够复用父类的某些特性、功能、方法等,如果父级是抽象类,还可以抽取子级中的功能特性,如果父级是接口,还可以在父级中定义一些规范(例如抽象方法),让每个子类都按照父级中的约定进行实现。
在Maven中,模块间的继承与Java的继承是类似的,可以将共性抽取到父 pom
中,通过子 pom
继承父 pom
来复用配置和约束。
2.1.可继承的标签
可继承的标签太多了,不一一例举,这里就列一些我们在开发中常用的可继承的标签:
groupId
、version
:坐标分组和版本,artifactId 不能继承。dependencies
:依赖配置denpendencyManagement
:依赖管理配置properties
:自定义属性,类似于定义一个变量repositories
:仓库配置distributionManagement
:项目部署的仓库配置build
:插件、插件管理、源码输出位置等配置
2.2.超级POM
所有的 pom.xml
文件都会默认继承 super pom,在 super pom 中定义了这么几个配置:
- 构件与插件仓库的地址
- 源码、测试代码以及资源文件
resources
的默认路径 - 编译及打包后的文件路径
这也是为什么我们创建一个Maven项目之后,只要在 Maven 约定好的路径中编写我们的代码,其他的几乎什么都不用配置,就可以直接进行构建,也是一种约定优于配置的思想体现。
super pom 的位置在Maven主目录的lib
文件夹下面,找到一个叫maven-model-builder.jar
的文件,在这个 jar 包的\org\apache\maven\model\pom-4.0.0.xml
路径下。如果使用的是idea的话,直接双击 shift
输入 pom-4.0.0.xml
即可:
<project><modelVersion>4.0.0</modelVersion><repositories><repository><id>central</id><name>Central Repository</name><url>https://repo.maven.apache.org/maven2</url><layout>default</layout><snapshots><enabled>false</enabled></snapshots></repository></repositories><pluginRepositories><pluginRepository><id>central</id><name>Central Repository</name><url>https://repo.maven.apache.org/maven2</url><layout>default</layout><snapshots><enabled>false</enabled></snapshots><releases><updatePolicy>never</updatePolicy></releases></pluginRepository></pluginRepositories><build><directory>${project.basedir}/target</directory><outputDirectory>${project.build.directory}/classes</outputDirectory><finalName>${project.artifactId}-${project.version}</finalName><testOutputDirectory>${project.build.directory}/test-classes</testOutputDirectory><sourceDirectory>${project.basedir}/src/main/java</sourceDirectory><scriptSourceDirectory>${project.basedir}/src/main/scripts</scriptSourceDirectory><testSourceDirectory>${project.basedir}/src/test/java</testSourceDirectory><resources><resource><directory>${project.basedir}/src/main/resources</directory></resource></resources><testResources><testResource><directory>${project.basedir}/src/test/resources</directory></testResource></testResources> </build>
</project>
2.3.手动引入自定义父POM
父 pom
的引入语法很简单,在parent
标签中添加构件坐标即可,类似于dependency
引入依赖:
<parent><groupId></groupId><artifactId></artifactId><version></version><relativePath></relativePath>
</parent>
这里的 relativePath
指的是父 pom.xml
所在的相对路径,默认值是 ../pom.xml
,如下图:
这也是 Maven 建议的目录组织形式,如果想将 parent 与 child 放到同一级目录,则需要修改为:<relativePath>../parent/pom.xml</relativePath>
,如下图:
修改到其他目录同理,同步修改相对路径即可,但这里建议使用默认的目录组织形式。
在配置好<relativePath>
,子模块会优先从上级目录中查找pom.xml
,如果查不到则到本地仓库中查找,如果还是查不到则会从远程仓库中查找,我们经常使用的 SpringBoot 就是通过这种方式引入的:
<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.1.6.RELEASE</version>
</parent>
3.模块的聚合
在上一篇 Maven 依赖中我们创建了一个拥有三个子模块的 Maven 项目 dependency-demo
:
在这个项目中,demo-a
依赖 demo-b
, demo-b
依赖 demo-c
, 在这种情况下,我们需要先 install
c ,再 install
b ,最后再构建 a,执行起来非常麻烦,为了处理这个问题,Maven 引入了聚合机制,可以将这三个模块聚合在一起,一次性完成构建。
3.1.聚合的注意事项
聚合的语法也非常简单,只需要在父目录的 pom.xml
中添加 <modules>
即可:
<modules><module>demo-a</module><module>demo-b</module><module>demo-c</module>
</modules>
这里需要注意的是,<module>
中填写的并不是 artifactId
,而是需要被聚合的模块的 文件目录 的相对路径,注释里面的描述是:
Each module listed is a relative path to the directory containing the module.
假如我们将 demo-a
的文件夹名称修改为 demo-aa
,即使artifactId
没有变,这里也需要填写为:
<modules><module>demo-aa</module><module>demo-b</module><module>demo-c</module>
</modules>
同理,如果不是 parent 项目在聚合子模块,而在a、b、c 同一级目录下,新建一个聚合模块来做聚合,则此处应该修改为。
<modules><module>../demo-a</module><module>../demo-b</module><module>../demo-c</module>
</modules>
综上,一般情况下,我们都将文件目录与 artifactId 保持一致,同时也会直接在父 pom.xml
中聚合子模块,这样的配置最简洁、最不容易出错,这也是 Maven 中约定由于配置的体现。
3.2.反应堆(reactor)
Maven 的反应堆是将多个模块的项目按照一定的顺序进行构建,我们使用上面聚合的项目来做一次构建:
mvn clean install
注意上面的执行顺序,先构建的是配置了聚合关系的聚合模块,然后才是子模块,子模块构建的时候会检查有没有依赖的模块,如果有就先构建依赖的模块。所以这里按照被依赖的顺序,由底层向上层进行构建。
因此,我们的模块之间不能出现循环依赖的情况,假如在demo-c
中引入demo-a
的依赖,此时构建就会报错。
The projects in the reactor contain a
cyclic reference
: Edge between ‘Vertex{label=‘com.ls.maven:demo-c:1.0.0’}’ and ‘Vertex{label=‘com.ls.maven:demo-a:1.0.0’}’ introduc
es to cycle in the graph com.ls.maven:demo-a:1.0.0 --> com.ls.maven:demo-b:1.0.0 --> com.ls.maven:demo-c:1.0.0 --> com.ls.maven:demo-a:1.0.0
在实际的开发中,有时候我们的项目比较庞大,如果每次都完整的进行构建,耗时就会很长。此时我们可以在构建指令上加上一些参数,以便于我们选择性的构建我们需要的项目,通过mvn -h
查看。
usage: mvn [options] [<goal(s)>] [<phase(s)>]Options:-am,--also-make If project list is specified, alsobuild projects required by thelist-amd,--also-make-dependents If project list is specified, alsobuild projects that depend onprojects on the list-B,--batch-mode Run in non-interactive (batch)mode (disables output color)-b,--builder <arg> The id of the build strategy touse-C,--strict-checksums Fail the build if checksums don'tmatch-c,--lax-checksums Warn if checksums don't match-cpu,--check-plugin-updates Ineffective, only kept forbackward compatibility-pl,--projects <arg> Comma-delimited list of specifiedreactor projects to build insteadof all projects. A project can bespecified by [groupId]:artifactIdor by its relative path
这里有特别多的参数,我随便复制了一部分,上面的-pl
和-am
是比较常用的参数,意思是,构建指定的项目以及它所依赖的项目。
pl
:指定构建某一个项目am
:构建项目的同时,构建它依赖的项目
假如我想指定构建demo-b
及其依赖的模块demo-c
,则可以用下面的指令:
mvn clean install -pl demo-b -am
4.依赖管理及属性配置
我们在做Java开发的时候,往往会将一些常量,公用的配置抽取到一个单独的文件中进行管理,这样我们在修改这些配置的时候,就有一个统一的入口,而不需要在这个项目中到处去找。
Maven的配置也是一样的,我们往往会把子模块中使用到的依赖以及版本号等,抽取到父模块中由子模块直接继承。
4.1.依赖管理
以Mysql连接为例,一般只有持久化相关的模块才会需要引入这个包。我们既要做到统一配置,又要做到只有部分模块引入,就可以在parent
使用依赖管理:<dependencyManagement/>
:
<dependencyManagement><dependencies><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.29</version></dependency></dependencies>
</dependencyManagement>
然后在需要使用到MySQL子模块中使用dependency
进行引入,这里就不需要填写版本号了:
<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId>
</dependency>
4.2.属性配置
属性配置就类似于声明变量,其语法为:
<properties><声明的属性key>声明的属性Value</声明的属性key>
</properties>
然后在其他的标签中可以使用${声明的属性key}
这个语法来获取value的值,于是上面的MySQL依赖就可以改为:
<properties><mysql-connector-java.verison>8.0.29</mysql-connector-java.verison>
</properties><dependencyManagement><dependencies><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>${mysql-connector-java.verison}</version></dependency></dependencies>
</dependencyManagement>
我们可以通过这种方式灵活的组织项目,将需要经常修改的版本号放到属性配置中管理,例如可以将demo-a
与 demo-b
中的依赖版本抽取到父pom
中:
<groupId>com.ls.maven</groupId>
<artifactId>dependency-demo</artifactId>
<packaging>pom</packaging>
<version>1.0.3</version><modules><module>demo-a</module><module>demo-b</module><module>demo-c</module>
</modules><name>dependency-demo</name><properties><demo-dependency.verion>1.0.3</demo-dependency.verion>
</properties><dependencyManagement><dependencies><dependency><groupId>com.ls.maven</groupId><artifactId>demo-b</artifactId><version>${demo-dependency.verion}</version></dependency><dependency><groupId>com.ls.maven</groupId><artifactId>demo-c</artifactId><version>${demo-dependency.verion}</version></dependency></dependencies>
</dependencyManagement>
然后分别修改demo-a
、demo-b
中的依赖:
- demo-a:
<parent><artifactId>dependency-demo</artifactId><groupId>com.ls.maven</groupId><version>1.0.2</version></parent><modelVersion>4.0.0</modelVersion><artifactId>demo-a</artifactId><name>demo-a</name><dependencies><dependency><groupId>com.ls.maven</groupId><artifactId>demo-b</artifactId></dependency></dependencies>
- demo-b:
<parent><artifactId>dependency-demo</artifactId><groupId>com.ls.maven</groupId><version>1.0.2</version> </parent> <modelVersion>4.0.0</modelVersion><artifactId>demo-b</artifactId><name>demo-b</name><dependencies><dependency><groupId>com.ls.maven</groupId><artifactId>demo-c</artifactId></dependency> </dependencies>
后续开发的过程中,统一修改版本号即可,例如通过Idea的批量修改将1.0.2
修改 为 1.0.3
,然后尝试打包:mvn clean install
:
5.总结
本篇主要讲述了Maven中的模块继承与聚合、父pom
中的依赖管理、属性配置等的特性,并通过一个简单的demo来演示这些特性,总结一下:
-
继承:
- super pom 是Maven最顶层的POM,它的存在让我们几乎不能做任何配置就可以完成项目构建
- 可以通过
<parent>
标签,让子模块的pom 继承 父模块的pom - 父模块的打包类型为
<packaging>pom</packaging>
- 注意
<relativePath>
指的的相对路径,默认为../xml.pom
-
聚合:
- 聚合的目的:将多个模块聚合在一起,一次性构建
<module>
中填写的是相对文件目录名,而不是artifactId
- 反应堆可以自动先构建依赖的模块,但是要注意不能产生循环依赖
- 如果只需要构建一部分模块,可以使用构建指令裁剪反应堆
-
依赖管理与属性配置:
<dependencyManagement>
可以配置好需要继承的依赖坐标,子模块继承后不需要再输入版本号<properties>
可以配置变量,并通过${}
进行引用
通过本篇的内容,就可以在实际的开发中搭建自己的多模块项目了,Maven部分的内容就接近尾声了,下一篇将会讲 Maven的插件配置。
相关文章:

【Maven】(五)Maven模块的继承与聚合 多模块项目组织构建
文章目录1.前言2.模块的继承2.1.可继承的标签2.2.超级POM2.3.手动引入自定义父POM3.模块的聚合3.1.聚合的注意事项3.2.反应堆(reactor)4.依赖管理及属性配置4.1.依赖管理4.2.属性配置5.总结1.前言 本系列文章记录了 Maven 从0开始到实战的过程,Maven 系列历史文章清…...

Linux 常用软件安装(jdk,redis,mysql,minio,kkFileView)
1.jdk安装 查询所有跟Java相关的安装的rpm包 rpm -qa | grep java卸载所有跟openjdk相关的包: 执行命令。删除以上除了noarch 结尾的所有文件 rpm -e --nodeps java-1.8.0-openjdk-1.8.0.252.b09-2.el8_1.x86_64 rpm -e --nodeps java-1.8.0-openjdk-headless-1.8.0…...

单链表及其相关函数
实现功能BuySListNode ————————————申请一个新节点并赋值SListLength —————————————计算链表的长度SListPushBack————————————尾插SListPushFront————————————头插SListPopBack—————————————尾删SListPopFront—…...

Linux段错误调试
1、设置ulimit ulimit -a 查看 ulimit -c 2048 设置core大小 2、设置core文件信息 下面两个设置需要在root下设置,否则权限不通过 echo 1>/proc/sys/kernel/core_uses_pid echo "/tmp/corefile-%e-%p-%t" >/proc/sys/kernel/core_pattern 3、编译…...

Gopro卡无法打开视频恢复方法
下边来看一个文件系统严重受损的Gopro恢复案例故障存储: 120G SD卡故障现象:客户正常使用,备份数据时发现卡无法打开,多次插拔后故障依旧。故障分析:Winhex查看发现0号分区表扇区正常,这应该是一个exfat格式的文件系统,但是逻辑盘…...

vmware虚拟机与树莓派4B安装ubuntu1804 + ros遇到的问题
如题所示,本人在虚拟机上安装ubuntu1804,可以很容易安装,并且更换系统apt源和ros源,然后安装ros,非常顺利,但是在树莓派4B上安装raspiberry系统就遇到了好多问题。 树莓派我烧录的是这个镜像:ub…...

JS逆向hook通用脚本合集
1. cookie 通用hook Cookie Hook 用于定位 Cookie 中关键参数生成位置,以下代码演示了当 Cookie 中匹配到了 v 关键字, 则插入断点 (function () {var cookieTemp ;Object.defineproperty(document, cookie, {set: function (val) {if (val.indexOf(v…...

nacos的介绍和下载安装(详细)
目录 一、介绍 1.什么是nacos(含有官方文档)? 2.nacos的作用是什么? 3.什么是nacos注册中心? 4.核心功能 二、下载安装 一、介绍 1.什么是nacos(含有官方文档)? 一个更易于…...

【算法经典题集】前缀和与数学(持续更新~~~)
😽PREFACE🎁欢迎各位→点赞👍 收藏⭐ 评论📝📢系列专栏:算法经典题集🔊本专栏涉及到的知识点或者题目是算法专栏的补充与应用💪种一棵树最好是十年前其次是现在前缀和一维前缀和k倍…...

寻找时空中的引力波:科学家控制量子运动至量子基态
据英国每日邮报报道,时空织布里的涟漪或可以揭示宇宙在140亿年前是如何产生的,然而寻找这些名为“引力波”的涟漪却一直难以捉摸。现在美国科学家们声称他们发现了改善用于检测宇宙大爆炸的引力波的探测器的方法。 宇宙大爆炸残留的引力波 美国加州理…...

第六讲:ambari-web 模块二次开发
上述图片为 Ambari 部署及操作 hdp 集群相关的部分界面截图。这些页面如果想调整的话,比如汉化,二次开发等,则可以修改 ambari-web 模块的源码来实现。 一、介绍 ambari-web 模块涉及到的界面有: HDP 集群部署向导已安装服务的仪表板、配置界面等主机列表及详细信息告警列…...

echarts--提示框显示不全问题记录
最近接手一个同事之前做的网页,发现里面使用echarts来绘制各类图表;有2个问题一个是提示框显示不全,另一个就是绘制总是有部分数据显示不全。后者就是div宽度问题。。。无语,说下前面一个问题吧,记录一下。 tooltip组…...

LeetCode 1653. 使字符串平衡的最少删除次数
LeetCode 1653. 使字符串平衡的最少删除次数 难度:middle\color{orange}{middle}middle Rating:1794\color{orange}{1794}1794 题目描述 给你一个字符串 sss ,它仅包含字符 ′a′a′a′ 和 ′b′b′b′ 。 你可以删除 sss 中任意…...

聊一聊代码重构——程序方法和类上的代码实践
使用工厂方法取代构造方法 构造方法的问题 我们使用构造方法来初始化对象时候,我们得到的只能是当前对象。而使用工厂方法替换构造方法,我们可以返回其子类型或者代理类型。这让我们可以通过不同的实现类来进行逻辑实现的变化。 更重要的一点是&#…...

嵌入式学习笔记——寄存器开发STM32 GPIO口
寄存器开发STM32GPIO口前言认识GPIOGPIO是什么GPIO有什么用GPIO怎么用STM32上GPIO的命名以及数量GPIO口的框图(重点)输入框图解析三种输入模式GPIO输入时内部器件及其作用1.保护二极管2.上下拉电阻(可配置)3.施密特触发器4.输入数…...

[ 攻防演练演示篇 ] 利用通达OA 文件上传漏洞上传webshell获取主机权限
🍬 博主介绍 👨🎓 博主介绍:大家好,我是 _PowerShell ,很高兴认识大家~ ✨主攻领域:【渗透领域】【数据通信】 【通讯安全】 【web安全】【面试分析】 🎉点赞➕评论➕收藏 养成习…...

程序设计与 C 语言期末复习
程序设计与 C 语言 1.计算机语言与编译 机器语言:一串仅由 0 和 1 序列表示的语言。计算机只能识别和接受 0 和 1 组成的指令。 符号语言(汇编语言):用一些英文字母和数字表示一个指令。 符号语言(汇编语言…...

05-思维导图Xmind快速入门
文章目录5.1 认识思维导图5.2 Xmind的主要结构及主题元素5.2.1 Xmind的多种结构5.2.2 主题分类5.2.3 Xmind的主题元素章节总结5.1 认识思维导图 什么是思维导图? 思维导图是一种将思维进行可视化的实用工具。 具体实现方法是用一个关键词去引发相关想法࿰…...

使用去中心化存储构建网站
今天的大多数网站都遵循后端服务器到前端代码的架构。但在 Web3 应用程序中,前端代码不具有与受智能合约保护的后端代码相同的去中心化性和弹性。那么如何使网站像智能合约一样具有弹性呢? 该体系结构似乎很简单: 创建一个没有服务器的静态…...

L - Let‘s Swap(哈希 + 规律)
2023河南省赛组队训练赛(四) - Virtual Judge (vjudge.net) 约瑟夫最近开发了一款名为Pandote的编辑软件,现在他正在测试,以确保它能正常工作,否则,他可能会被解雇!Joseph通过实现对Pandote上字符串的复制和…...

c语言自动内存回收(RAII实现)
简述 什么是RAII RAII(Resource Acquisition Is Initialization)是c之父Bjarne Stroustrup提出的概念。资源一般分三个步骤:获取、使用和销毁,而在自由使用内存的c语言中,资源的销毁常常是程序员容易遗漏的事情&…...

Node.js的简单学习一-----未完待续
文章目录前言学习目标一、初识Node.js1.1 回顾与思考1.1.1 需要掌握那些技术1.1.2 浏览器中的JavaScript的组成部分1.2 Node.js简介1 什么是Node.js2 Node.js中的JavaScript运行环境3 Node.js 可以做什么1.3 Node.js环境的安装1.4 在Node.js环境中执行JavaScript 代码终端中的快…...

linux入门---粘滞位
为什么会有粘滞位 一台服务器有很多人使用,每个人在机器上都会有一个家目录,在家目录里可以实现自己想要的操作,但是有时候我们需要一个公共路径来完成一些操作,比如说资料分享产生临时文件的增删查改等等,这就好比我…...

关于正则表达式的讲解
以下内容源于《linux命令行与shell脚本编程大全【第三版】》一书的整理。 在shell脚本中成功运用sed编辑器和gawk程序的关键,在于熟练地使用正则表达式。 一、正则表达式的简介 1、正则表达式的定义 正则表达式(regular expression)是一个…...

贝塞尔曲线与B样条曲线
文章目录0.参考1.问题起源与插值法的曲线拟合1.1.问题起源1.2.拉格朗日插值1.3.“基”的概念1.4.插值存在的Runge现象2.贝塞尔曲线2.1.控制点的思想2.2.由控制点生成贝塞尔曲线2.3.多个控制点时的贝塞尔曲线公式2.4.贝塞尔曲线的递推公式2.5.贝塞尔曲线的性质3.B样条曲线3.1.B样…...

C语言-基础了解-24-C头文件
C头文件 一、C 头文件 头文件是扩展名为 .h 的文件,包含了 C 函数声明和宏定义,被多个源文件中引用共享。有两种类型的头文件:程序员编写的头文件和编译器自带的头文件。 在程序中要使用头文件,需要使用 C 预处理指令 #include…...

The 19th Zhejiang Provincial Collegiate Programming Contest vp
和队友冲了这场,极限6题,重罚时铁首怎么说,前面的A题我贡献了太多的罚时,然后我的G题最短路调了一万年,因为太久没写了,甚至把队列打成了优先队列,没把head数组清空完全,都是我的锅呜…...

用于<分类>的卷积神经网络、样本不平衡问题的解决
输入图像——卷积层——池化层——全连接层——输出 卷积层:核心,用来提取特征。 池化层:对特征降维。实际的主要作用是下采样,减少参数量来提高计算速度。 卷积神经网络的训练:前向传播(分类识别…...

网上订餐管理系统的设计与实现
技术:Java、JSP等摘要:随着信息技术的广泛使用,电子商务对于提高管理和服务水平发挥着关键的作用。越来越多的商家开始着手于电子商务建设。电子商务的发展为人们的生活提供了极大的便利,也成为现实社会到网络社会的真实体现。当今…...

Httpclient测试
在IDEA中有一个非常方便的http接口测试工具httpclient,下边介绍它的使用方法,后边我们会用它进行接口测试。如果IDEA版本较低没有自带httpclient,需要安装httpclient插件1.插件2.controller进入controller类,找到http接口对应的方…...