从0到0.1学习 maven(三:声明周期、插件、聚合与继承)
该文章为maven系列学习的第三篇,也是最后一篇
第一篇快速入口:从0到0.1学习 maven(一:概述及简单入门)
第二篇快速入口:从0到0.1学习 maven(二:坐标、依赖和仓库)
文章目录
- 啥子叫生命周期
- 生命周期详解
- clean生命周期
- default生命周期
- site生命周期
- 插件
- 插件配置
- 插件解析
- 聚合
- 继承
- 可继承的元素
- 依赖管理
- 插件管理
- 小结
- 反应堆
- 裁剪反应堆
啥子叫生命周期
构建步骤包括项目清理,初始化,编译,测试,打包,集成测试,验证,部署等等。maven将这些过程进行了抽象与统一,映射到了生命周期上。
可以将maven的生命周期理解成设计模式中的模板方法。父类定义整体结构,子类进行具体方法的实现和重写。在控制整体结构的同时也增加了可拓展性。maven没有对这些步骤提供实现,但是提供了默认绑定的插件,因此实际上每个步骤都是通过插件完成的。
生命周期详解
实际上,maven中的生命周期分成了三套,分别为clean,default与site,分别对应着 清理,构建与建立项目站点。每套生命周期都对应着一些有序的阶段。等下会详细介绍。三套生命周期本身是相互独立的,也就是调用clean不会影响到site。
clean生命周期
阶段1:pre-clean: 执行清理前需要完成的工作
阶段2:clean:清理上一次构建生成的文件
阶段3:post-clean:执行一些清理后需要完成的工作
阶段间是有序的,因此若想调用post-clean,会按preclean-clean-postclean的顺序执行。
default生命周期
在default周期中,定义了真正构建时需要的步骤。官方介绍可以参考:https://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html
- validate:验证项目是否正确,所有需要的信息是否都可用
- initialize:初始化例如属性的设置、 目录的创建等
- generate-sources:
- process-sources:处理项目主资源文件,一般是在src/main/resources中,完成变量替换等,再复制到项目输出的主classpath目录中。
- generate-resources
- proess-resources
- compile:编译源代码,一般是在src/main/java目录下
- process-classes
- generate-test-sources
- process-test-sources:处理测试资源文件。一般是在src/test/resources目录下,将该目录下的java文件编译输出到测试的classpath目录中。
- generate-test-resources
- process-test-resources
- test-compile:编译项目的测试代码。一般在src/test/java目录下。编译好后输出到测试的classpath目录中。
- process-test-classes
- test:用单元测试框架来测试编译后的源代码,测试代码不会打包或者部署。
- prepare-package
- package:用指定的后缀格式将编译后的代码进行打包
- pre-integration-test
- integration-test
- post-integration-test
- verify
- install:将package安装到本机的仓库中,以供其他依赖它的项目使用
- deploy:将最终的package复制到远程仓库中,以供其他开发者与项目共享
site生命周期
该周期的主要作用为建立和发布项目站点。根据pom中包含的信息,自动生成站点。
- pre-site:完成一些生成项目站点之前需要的工作
- site:生成项目站点文档
- post-site:完成一些生成项目站点之后的工作
- site-deploy:将生成的项目站点发布到服务器上。
插件
首先介绍一下插件目标,可以将一个小功能点理解成一个目标。前面提到核心功能都是通过插件的形式来实现的,但是针对一个功能点就开发一个插件显然会有很多冗余代码。因此一个插件可能会包含多个插件目标。
生命周期会与插件相互绑定,例如对于A过程, 插件B可以完成该任务,因此将AB进行绑定。如果某过程没有绑定插件,那该过程就不会有实际行为。
为了让用户几乎不用配置就可以构建maven项目,maven会对主要的生命周期阶段进行内置的插件绑定。
另外,一个插件也可以绑定多个阶段,例如clean生命周期的三个阶段都绑定在了maven-clean-plugin:clean插件上。
除了内置的绑定之外,用户也可以对阶段使用的插件进行自定义的绑定。
举一个自定义绑定插件的例子
<build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-source-plugin</artifactId><version>2.2.1</version><executions><execution><id>attach-sources</id><phase>verify</phase><goals><goal>jar</goal></goals></execution></executions></plugin></plugins>
</build>
可以看到,在execution元素下,指定了phase(阶段)和goal(目标)。
尝试删除phase阶段,再次执行mvn verfify,执行依然成功。因为很多插件的目标在编写的时候已经默认绑定了阶段。可以通过mvn help:describe -Dplugin=xxxxx -Ddetail来查看具体信息
运行mvn help:describe -Dplugin=org.apache.maven.plugins:maven-source-plugin:2.2.1 -Ddetail看一下我们刚刚用的包的细节。

第五行:Bound to phase: package 指明了他绑定的默认生命周期阶段时package。
ps: 如果不加版本号,则自动获取最新的版本。加了detail是为了更详细的信息。如果仅仅想知道某个目标的信息,可以使用goal参数。
插件配置
命令行配置
maven沿用了java的命令行传参模式即“-D”
例如上述例子中 -Dplugin=xxx就表示着传递 名为plugin,值为xxx的参数。
POM中插件全局配置
对于很少或不会改变的参数,直接写死在pom文件中。
直接在version下面加一个configuration的子标签
<configuration><source>1.5</source><target>1.5</target>
</configuration>
POM中配置任务参数
还可以为某个插件任务配置特定的参数
<configuration><tasks><echo>I am a task</echo></tasks>
</configuration>
插件解析
首先,需要了解一个插件前缀的概念。我们刚刚使用了mvn help:describe"实际上是maven-help-plugin插件的describe目标。这里help就是插件前缀,其结构是groupId:artifactId。复习一下,依赖仓库的路径groupId/artifactId/maven-metadata.xml,插件仓库的元数据是在groupId/maven-metadata.xml下的。
插件像构件一样,以坐标的形式存储在maven仓库中。
插件仓库的子元素配置和依赖仓库完全相同。
<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>
如果是maven的官方插件(groupId=org.apache.maven.plugins),则可以省略groupId配置。
对于核心插件,maven为它们在超级pom(所有maven项目的父pom)中预先设定了版本。因此核心插件可以不用指定版本。
对于非核心插件,类似于仓库的版本解析,插件也有元数据文件。maven遍历本地与远程插件仓库,找到lastest和release。maven2会使用latest,maven3会使用release。
聚合
实际项目中,可能是会由多个项目组合起来的,需要对每个项目进行打包构建。如果每次都一个一个地去模块对应的目录下构建那是相当麻烦。因此聚合,也叫多模块 就是在一个目录可以构建项目中的所有包。
首先需要创建出一个额外的模块,并写pom文件
<?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.company.sc</groupId><artifactId>demo</artifactId><version>1.0.0-SNAPSHOT</version><packaging>pom</packaging><name>a_practise_demo</name><description>用于练习聚合的项目</description><modules><module>module_name_1</module><module>module_name_2</module><module>module-name-3</module></modules>
</project>
它与普通的模块有三处不同
- packaging的值为pom,这标志着该模块为聚合模块。对其需要打包的子模块,都遵照各模块的packaging类型。
- 多了一层modules,标记着该聚合模块包含哪些模块。值得注意的是这里module子标签实际上不是真正的模块名,而是模块的目录名。因此如果这个聚合模块不是其他模块的父文件夹的话,需要将module元素的内容改成能指向正确模块的目录。
- 实际上,该聚合模块只会包含一个pom.xml文件,不会有test或java目录和代码。它仅仅是帮助构建的工具,并没有实际的内容。
继承
在maven世界里也有继承这个概念。像聚合一样,需要单独抽出一个目录,编写父pom以完成“一处声明,多处使用”的目的。
<?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.company.sc</groupId><artifactId>demo-parent</artifactId><version>1.0.0-SNAPSHOT</version><packaging>pom</packaging><name>a_practise_demo</name>
</project>
它与聚合有两点相同:
- 除了pom之外没有其他目录
- packaging使用的也是pom
继承父类的子模块需要加入如下内容
<parent><groupId>com.company.sc</groupId><artifactId>demo-parent</artifactId><version>1.0.0-SNAPSHOT</version><relativePath>../dir1/dir2/pom.xml</relativePath>
</parent>
groupId, artifactId, version 是定义坐标系的三个最基本的元素,是必须的。relativePath表示父pom的相对路径,默认值是…/pom.xml,也就是maven默认父pom在上一层目录下。
另外,如果有聚合模块的话,该继承模块也需要被添加到modules标签下。
可继承的元素
- groupId
- version
- description
- organization
- inceptionYear:项目的创建年份
- url:项目的url地址
- developers
- contributors
- distributionManagement:项目的部署配置
- issueManagement:项目的issue信息
- ciManagement:项目的持续集成系统信息
- scm:项目的版本控制系统信息
- mailingLists
- properties:自定义maven属性
- dependencies:项目的依赖配置
- dependencymanagement:项目的依赖管理配置
- repositories:项目的仓库配置
- build:包括项目的源码目录配置、输出目录配置、插件配置等
- reporting:包括项目的报告输出目录配置,报告插件配置等
依赖管理
父类的依赖可以被子类继承,但不一定所有的父类依赖都会被每个子类使用。这里maven提供了dependencyManagement元素,能让子模块继承到父模块的依赖配置,又能保证灵活性。因为dm元素下的依赖声明不会引入实际的依赖,但却能控制依赖。比如可以在父pom中声明依赖的groupId, artifactId, version,scope,子模块中就只需要groupId, artifactId,其他都可以从父类中继承。
依赖范围import只在dependencyManagement中才有效果。它的作用是将某pom中dm标签下的配置导入并合并到当前pom的dm元素中。假设另外一个模块想要导入我们前面的父类pom,可以通过以下配置。
<dependencyManagement><dependencies><dependency><groupId>com.company.sc</groupId><artifactId>demo-parent</artifactId><version>1.0.0-SNAPSHOT</version><type>pom</type><scope>import</scope></dependency></dependencies>
</dependencyManagement>
一般import都会指向打包类型为pom的模块,因此type元素的值为pom。
插件管理
类似于刚刚的依赖管理,插件相应地也可以使用pluginManagement进行管理:在父pom中配置plugin元素,当子pom中继承并配置了对应地groupId和artifactId,pm中的配置才会生效。
小结
对于聚合模块,它知道有哪些被聚合的模块,但是被聚合的模块不知道它。对于继承模块,继承该模块的子模块知道他,但是他不知道都有谁继承了他。两个关系刚好相反,但是配置的时候packaging都必须是pom。在实际项目中,一个pom可能又当聚合pom又当父pom。
反应堆
反应堆指的是所有的模块形成的一个构建结构。拿以下模块为例子,该部分从demo的pom中提取。
<modules><module>module_name_child_1</module><module>module_name_father</module><module>module_name_no_father</module>
</modules>
反应堆的构建顺序与声明顺序不一定一致,这个要取决于聚合与依赖关系。实际的构建顺序应为
demo->module_name_father->module_name_child_1->module_name_no_father
demo是聚合模块的起点,肯定是第一个构建的,然后按照顺序读取到了module_name_child_1,检查到它依赖着module_name_father,于是先去构建module_name_father。构建好了之后再构建module_name_father。接着继续按顺序,构建到module_name_no_father。一般来讲,依赖关系会将反应堆构建为有向无环图,如果有环,在构建时maven就会报错。
裁剪反应堆
如果想构建反应堆中的某些模块,可以使用mvn -h
- -am (–also-make)同时构建所列模块的依赖模块
- -amd(-also-make-dependens)同时构建 依赖于所列模块的模块
- -pl(–projects )<args> 构建指定的模块,用逗号做分隔符
- -rf(-resume-from)<args> 从指定的模块构建反应堆
举个例子,假设a依赖于b和c,如果用-am a的话,就会同时构建a b c。如果用-amd b的话,就会构建 a b。假设之前的构建顺序是 a b c d,那-rf c 就会构建c和d
相关文章:
从0到0.1学习 maven(三:声明周期、插件、聚合与继承)
该文章为maven系列学习的第三篇,也是最后一篇 第一篇快速入口:从0到0.1学习 maven(一:概述及简单入门) 第二篇快速入口:从0到0.1学习 maven(二:坐标、依赖和仓库) 文章目录啥子叫生命周期生命周期详解clean生命周期def…...
【直击招聘C++】2.5 this指针
2.5 this指针一、要点归纳1.什么是this指针2.this指针的深入讨论程序1程序23.类成员函数返回对象和返回对象引用的区别二、面试真题解析面试题1面试题2一、要点归纳 1.什么是this指针 this指针是隐含于每一个类对象的特殊指针,该指针值是一个正在被某个成员函数操作…...
spark数据清洗练习
文章目录准备工作删除缺失值 > 3 的数据删除星级、评论数、评分中任意字段为空的数据删除非法数据hotel_data.csv通过编写Spark程序清洗酒店数据里的缺失数据、非法数据、重复数据准备工作 搭建 hadoop 伪分布或 hadoop 完全分布上传 hotal_data.csv 文件到 hadoopidea 配置…...
Android 12首次开机启动Launcher前黑屏问题解析
在工作中,对于系统开发确实有些难度,特别是在开机阶段遇到的问题,比如开机动画播放完毕进入锁屏界面黑屏几秒然后进入 锁屏界面,这就需要根据开机日志来分析问题所在,在工作中遇到的几种黑屏情况做下记录首次开机进入L…...
使用 LSSVM 的 Matlab 演示求解反常微分方程问题(Matlab代码实现)
目录 💥1 概述 📚2 运行结果 🎉3 参考文献 👨💻4 Matlab代码 💥1 概述 LSSVM的特性 1) 同样是对原始对偶问题进行求解,但是通过求解一个线性方程组(优化目标中的线性约束导致…...
动态规划-背包问题
文章目录一、背包问题1. 背包问题简介2. 背包问题解决方法二、01 背包问题1. 实现思路2. 实现代码三、完全背包问题1. 实现思路2. 实现代码四、多重背包问题(一)1. 实现思路2. 实现代码五、多重背包问题(二)1. 实现思路2. 实现代码…...
计算24点与运算符重载
十几年前写过一个算24点的程序。记得当时有点费劲,不过最后总算捣鼓出来了。前几天突然想再写一次,结果轻松地写出来了。C,总行数不多,带命令行界面和注释共200行不到;利用了面向对象和运算符重载来简化代码。 首先谈…...
MES系统智能工厂,搭上中国制造2025顺风车
MES在电子制造业中的应用日益广泛,越来越多的厂商已经购置或自行开发了MES,并将其作为“智能化工厂”。国内大大小小、各行各业都有上百个MES系统,还有很多的国外MES系统,怎么才能在MES系统公司中找到适合自己的MES?希…...
【LeetCode】每日一题(1)
目录 题目: 解题思路: 代码: 写在最后: 题目: 这是他给出的接口: class Solution { public:int fillCups(vector<int>& amount) {} }; 作为一个数学学渣,我想不出厉害的数学算法…...
SpringCloud-Netflix学习笔记11——Hystrix实现服务降级
服务降级 是什么? 整体资源快不够了,忍痛将某些服务先关掉,待渡过难关,再开启回来。 如下图,在某一个时间段,访问服务A的请求特别多,而访问服务B和服务C的请求特别少,这时我们可以把…...
Oracle Dataguard(主库为 Oracle rac 集群)配置教程(03)—— 创建 dataguard 数据库之前的准备工作
Oracle Dataguard(主库为 Oracle rac 集群)配置教程(03)—— 创建 dataguard 数据库之前的准备工作 / 本专栏详细讲解 Oracle Dataguard(Oracle 版本为11g,主库为双节点 Oracle rac 集群)的配置…...
零代码做分析报表的bi软件才是好软件
有些数据分析软件对IT的依赖比较重,在制作报表的过程中需要用到SQL,这就导致了IT人员懂技术不懂业务,业务人员懂业务不懂技术,数据分析做来做去总是差点什么的局面。要是遇到了IT部门相对较弱的情况,还会加重IT负担&am…...
linux ALSA 驱动架构
一、kernel Audio驱动架构主流有两大类,一类是SOC Machine架构,另一类是simple-card架构。 MTK、QCom主要采用machine架构,rockchip采用simple card架构。 二、Machine架构驱动介绍 machine 架构每家平台实现并不完全相同,mach…...
JDK 8 JVM内存结构详解
前言 本文所介绍的是 JDK 1.8 版本,其他版本的 JDK 在这里并不一定正确;内容主要摘自周志明的《深入理解Java虚拟机》一书的关键点,并根据自身的理解进行记录。感兴趣的同学可以去阅读原著。 JVM 的内存结构,主要包括以下 5 个区…...
黑马程序员 Linux 教程
目录Linux 简介不同应用领域主流操作系统Linux 系统历史Linux 系统版本Linux 安装安装方式网卡设置安装 SSH 连接工具使用 FinalShell 连接到 LinuxLinux 和 Windows 目录结构对比Linux 目录介绍Linux 常用命令Linux 命令初体验Linux 命令使用技巧Linux 命令格式文件目录操作命…...
文件操作 -- IO
文章目录文件操作 -- IO文件 :文件路径 :文件的类型java 中的文件操作文件内容的相关操作字节流的读和写操作字符流的读和写操作代码案例代码案例一 :代码案例二 :代码案例三 :文件操作 – IO 文件 : 文件相比大家都不陌生把 , 打…...
FPGA解析串口协议帧3.0版本,增加了错误重发功能,提供仿真文件以及源码
FPGA解析串口协议帧已经发布2个版本了,分别如下: 版本1:点击查看版本1 版本1详细介绍了串口协议帧的帧组成和设计思想,但设计粗糙,注释不详细; 版本1:点击查看版本2 版本2优化了代码,…...
365天深度学习训练营 第P6周:好莱坞明星识别
🍨 本文为🔗365天深度学习训练营 内部限免文章(版权归 K同学啊 所有)🍦 参考文章地址: 🔗第P6周:好莱坞明星识别 | 365天深度学习训练营🍖 作者:K同学啊 | 接…...
一文读懂 Zebec Chain 的“先行网络” Nautilus 链
最近,Zebec 上线了 DAO 治理系统后,上线并通过了关于 Nautilus 链的提案,这也是DAO系统上线后通过的首个提案。 Nautilus 链可以被看作是Zebec Chain上线前的“先行”链,并且是目前行业内为数不多的以“Layer3”作为特点的模块化通…...
FuzzyMathematicalModel模糊数学模型-2-多目标模糊综合评价案例分享
主函数:clc, clear% 输入模糊矩阵的原型x [4700 6700 5900 8800 76005000 5500 5300 6800 600004.0 06.1 05.5 07.0 06.80030 0050 0040 0200 01601500 0700 1000 0050 0100];r muti_objective_fuzzy_analysis(x);% 各指标在决策中占的权重(专家系统,自…...
【Axure高保真原型】引导弹窗
今天和大家中分享引导弹窗的原型模板,载入页面后,会显示引导弹窗,适用于引导用户使用页面,点击完成后,会显示下一个引导弹窗,直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…...
SkyWalking 10.2.0 SWCK 配置过程
SkyWalking 10.2.0 & SWCK 配置过程 skywalking oap-server & ui 使用Docker安装在K8S集群以外,K8S集群中的微服务使用initContainer按命名空间将skywalking-java-agent注入到业务容器中。 SWCK有整套的解决方案,全安装在K8S群集中。 具体可参…...
【OSG学习笔记】Day 18: 碰撞检测与物理交互
物理引擎(Physics Engine) 物理引擎 是一种通过计算机模拟物理规律(如力学、碰撞、重力、流体动力学等)的软件工具或库。 它的核心目标是在虚拟环境中逼真地模拟物体的运动和交互,广泛应用于 游戏开发、动画制作、虚…...
Qt/C++开发监控GB28181系统/取流协议/同时支持udp/tcp被动/tcp主动
一、前言说明 在2011版本的gb28181协议中,拉取视频流只要求udp方式,从2016开始要求新增支持tcp被动和tcp主动两种方式,udp理论上会丢包的,所以实际使用过程可能会出现画面花屏的情况,而tcp肯定不丢包,起码…...
Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility
Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility 1. 实验室环境1.1 实验室环境1.2 小测试 2. The Endor System2.1 部署应用2.2 检查现有策略 3. Cilium 策略实体3.1 创建 allow-all 网络策略3.2 在 Hubble CLI 中验证网络策略源3.3 …...
Golang dig框架与GraphQL的完美结合
将 Go 的 Dig 依赖注入框架与 GraphQL 结合使用,可以显著提升应用程序的可维护性、可测试性以及灵活性。 Dig 是一个强大的依赖注入容器,能够帮助开发者更好地管理复杂的依赖关系,而 GraphQL 则是一种用于 API 的查询语言,能够提…...
2025 后端自学UNIAPP【项目实战:旅游项目】6、我的收藏页面
代码框架视图 1、先添加一个获取收藏景点的列表请求 【在文件my_api.js文件中添加】 // 引入公共的请求封装 import http from ./my_http.js// 登录接口(适配服务端返回 Token) export const login async (code, avatar) > {const res await http…...
大模型多显卡多服务器并行计算方法与实践指南
一、分布式训练概述 大规模语言模型的训练通常需要分布式计算技术,以解决单机资源不足的问题。分布式训练主要分为两种模式: 数据并行:将数据分片到不同设备,每个设备拥有完整的模型副本 模型并行:将模型分割到不同设备,每个设备处理部分模型计算 现代大模型训练通常结合…...
USB Over IP专用硬件的5个特点
USB over IP技术通过将USB协议数据封装在标准TCP/IP网络数据包中,从根本上改变了USB连接。这允许客户端通过局域网或广域网远程访问和控制物理连接到服务器的USB设备(如专用硬件设备),从而消除了直接物理连接的需要。USB over IP的…...
LeetCode - 199. 二叉树的右视图
题目 199. 二叉树的右视图 - 力扣(LeetCode) 思路 右视图是指从树的右侧看,对于每一层,只能看到该层最右边的节点。实现思路是: 使用深度优先搜索(DFS)按照"根-右-左"的顺序遍历树记录每个节点的深度对于…...
