搞定Maven全功能,来从根上理解Maven拉包原理

news2024/12/27 13:42:07

  • 依赖

  • 生命周期与插件

  • 模块聚合

  • 模块继承

  • 属性

  • 版本管理

  • 环境配置

  • 私服

  • <dependencyManagement>的作用

在一次需求迭代中,我要求同事把写好的 RPC 接口打好包上传到公司私服上。然而,她并不熟悉 Maven,仅仅掌握了最基础的使用方法,而对于 Maven 背后的原理和一些常见的概念并不是很清晰。虽然她会使用 Maven 构建项目、引入依赖、打包等最基础的操作,但这些操作显然不足以完成任务。我意识到,我们需要提高团队的技能水平,并在公司内部组织了一次 Maven 的内部培训。这次培训帮助了同事们补充了一些基础知识,让她成功地完成了所需求。通过这次经历,我认识到,我们需要不断提高自己的技能,以适应快速变化的工作环境。因此,我希望我的经验能够帮助更多的人,让他们也能在工作中不断成长。 

依赖

依赖是我们在使用 Maven 构建项目时最常使用的功能,通过依赖标签,我们可以直接从Maven仓库中引入对应的Jar包,无需手动再将Jar添加到目录下了,可谓是十分方便,不过我们除了使用,还需要考虑多模块下依赖之间的关系。

依赖配置

这个大家应该都很熟悉了,通过<dependency>标签引入Maven依赖

 

引入依赖之后,刷新一下Maven依赖就可以引入相关的Jar包了。

依赖传递

依赖具有传递性,当我们引入了一个依赖的时候,就会自动引入该依赖引入的所有依赖,依次往下引入所有依赖。

比如我们引入了Druid数据库连接池的SpringBoot-Starter,那么就会自动引入一些依赖

 

如图,我们仅仅引入了druid-spring-boot-starter依赖,就自动引入了该依赖依赖的依赖。总而言之就是套娃就完事了。

我们将这三个依赖称为间接引入的依赖,而我们在<dependency>标签中引入的依赖称为直接依赖,那么如果这两个重复了并且版本不一样的话会怎么办呢,最后引入的到底是哪个版本呢,还是说都会引入呢?

如果重复了,遵从以下规则

简单来说,就是越在外层的优先级越高,如果同级的就按照配置顺序,配置顺序靠前的覆盖配置顺序靠后的。

可选依赖

可选依赖指对外隐藏当前所依赖的资源

 

配置了该选项之后,间接依赖就失效了。

排除依赖

排除依赖指主动断开间接依赖的资源

 

配置了该选项之后,间接依赖也会失效。

排除依赖和可选依赖的区别:

可选依赖是依赖提供者设置的,比如我们引入了Durid,那么该选项由Durid开发者设置

排除依赖由依赖引入者设置,比如我们引入了Durid,那么我们可以设置该选项

 

 

生命周期与插件

项目构建生命周期

Maven项目构建生命周期描述的是一次构建过程经历了多少个事件,我们可以把生命周期当成一个人的年龄。

Maven将生命周期划分为三个大阶段,类似于人类的婴儿,青年,入土

  • clean:清理工作

  • default:核心工作,例如编译,测试,打包,部署

  • site:产生报告,发布站点

第一个和第三个周期比较简单,我们重点介绍一下default阶段

先上一张劝退图

 

以上就是defalut阶段完整的生命周期,其中标红的地方,是几个比较重要的周期,在Idea的Maven工具中也能体现出来

当我们在Idea中点击这几个生命周期时,Maven会自动将之前所有的生命周期都执行到,就类似于如果我18岁了,那么我肯定经历过8岁。

插件

插件就是Idea中Maven工具的Plugins部分

 

 通过pom文件中的<build></build>标签引入新的插件

那么什么是插件呢?

  • 「插件与生命周期内的阶段绑定」 ,在「执行到对应生命周期时执行对应的插件功能」

  • 默认maven在各个生命周期上绑定有预设的功能

  • 通过插件可以自定义其他功能

 

上述自定义插件的作用指的是在generate-test-resources生命周期执行打jar包的操作。

其实简单的说,生命周期就是一个人的年龄阶段,而插件就是每个人在每个年龄需要做的事情

总结:

 

 Maven将一个项目构建的过程分为一长串连续的生命周期,在对应的生命周期会通过插件完成对应的事件,通过使用Maven的生命周期,我们可以获得我们需要的功能,可能是打jar包,可能是安装到本地仓库,可能是部署到私服。

模块聚合

当使用Maven进行多模块开发的时候,有可能出现A模块依赖B模块,B模块依赖C模块,那么我们如果想对A模块打包,那么就要先打包C模块,再打包B模块,最后打包A模块才能成功,否则会报错,并且,如果C模块更新了,我们也要手动更新所有依赖C模块的模块,这样是及不方便的,Maven为了更好的进行多模块开发,提供了模块聚合的功能。

作用:「聚合用于快速构建Maven工程,一次性构建多个项目/模块」

模块继承

还是在多模块项目开发中,多个子模块可能会引入相同的依赖,但是他们有可能会各自使用不同的版本,版本问题,有可能会导致最后构建的项目出问题,所以我们需要一种机制,来约定子模块的相关配置,于是就有了模块继承

作用:通过继承可以实现在子工程中沿用父工程中的配置

实现步骤:还是以ruoyi为例

  1. 在子工程中声明其父工程坐标与对应的位置

 

 

2.在父工程中定义依赖管理

 

继承除了依赖版本号之外,还会继承一些资源,如下图 

属性 

在Maven中,对于有些依赖可能需要保证相同的版本,比如Spring相关依赖,那么我们就需要一个机制来保证这些依赖的版本都相同,我们可以使用Maven中的属性,类似编程语言的全局变量。

Maven中有很多属性:

  1. 自定义属性

  2. 内置属性

  3. Setting属性

  4. Java系统属性

  5. 环境变量属性

    自定义属性

    作用:将一些字符串定义为变量,方便统一维护

内置属性

作用:使用Maven内置属性,快速配置一些文件

 

Setting属性

作用:使用Maven配置文件setting.xml中的标签属性,用于动态配置

Java系统属性

作用:读取Java系统属性

环境变量属性

作用:使用Maven环境变量

 

版本管理

对于我们的项目来说,如果我们将其放到一些Maven仓库中,那么就需要对其进行版本控制,我们可以看一下一些开源项目的Maven官网上的版本。

 

 pom文件配置

工程版本号约定

 

 

环境配置

一个项目,开发环境、测试环境、生产环境的配置文件必然不同,那么Maven就需要进行多环境配置管理

Maven多环境对应Idea中Maven工具的Profiles

 

 配置文件:通过<profiles>配置文件配置,一个profile代表一个可选项

然后我们在application.yml配置文件中设置即可,之后通过设置maven的profiles,就可以动态调整环境了。

私服

Maven私服指的是企业自己搭建的Maven仓库,通过Maven私服,第三方组织可以把自己组织内部的Maven依赖安装到私服上,提供给组织内部使用,搭建完私服之后,通过配置Maven,我们不止可以从中央仓库中获取Maven依赖,还可以从私服中获取Maven依赖。

下图是获取资源的过程,中央仓库的资源会从中央仓库获取,其他资源会从私服仓库获取

Maven私服指的是企业自己搭建的Maven仓库,通过Maven私服,第三方组织可以把自己组织内部的Maven依赖安装到私服上,提供给组织内部使用,搭建完私服之后,通过配置Maven,我们不止可以从中央仓库中获取Maven依赖,还可以从私服中获取Maven依赖。

下图是获取资源的过程,中央仓库的资源会从中央仓库获取,其他资源会从私服仓库获取

 

可以将这些仓库分为三大类

  • 「宿主仓库hosted」 :保存无法从中央仓库获取的资源

    • 自主研发

  • 第三方非开源项目

  • 「代理仓库proxy」

    • 代理远程仓库,通过nexus访问其他公共仓库

  • 「仓库组」 :将若干个仓库组成一个群组,简化配置,它仅仅是一种配置,不是真实的仓库

    • 比如我们可以将二课项目相关的依赖放到一个仓库组中,将抽奖项目的依赖放到一个仓库组中

创建私服仓库

点击create repository

 

本地仓库访问私服配置

配置本地仓库访问私服的权限(setting.xml文件),如果你想从这个仓库中获取或者部署资源,那么就需要server配置来验证权限,此处可以是不同的账号密码,不同的用户对于仓库的权限也不同。

<dependencyManagement>的作用

为了规范一个复杂项目中所有子模块的依赖版本,防止出现两个子模块a,b引用同一个依赖,但是一个的版本是1.0,一个的版本是2.0的这种情况。这不仅会导致版本不相同,而且会影响匹配的结果。

举个例子,假设子模块a和b都引入了x、y、z三个依赖,这三个依赖的版本都要求是相同的,这样才能匹配成功。但是如果子模块a引入的是1.0的版本,而子模块b引入的是2.0的版本,那么最终可能会出现版本不相同的问题,使得匹配失败。因此,我们需要在父工程的<dependencyManagement>中对依赖版本进行管理。在其中指定每个依赖项的版本,从而确保每个子模块的依赖版本都是相同的,避免版本不一致的问题。

 

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

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

相关文章

【24】linux进阶——初识shell

大家好&#xff0c;这里是天亮之前ict&#xff0c;本人网络工程大三在读小学生&#xff0c;拥有锐捷的ie和红帽的ce认证。每天更新一个linux进阶的小知识&#xff0c;希望能提高自己的技术的同时&#xff0c;也可以帮助到大家 另外其它专栏请关注&#xff1a; 锐捷数通实验&…

管家婆辉煌Ⅱ 13.32版安装方法

因管家婆辉煌版已经长期不更新&#xff0c;现已经出现蓝屏的问题&#xff0c;故此新开此贴&#xff0c;慢慢更新安装方法。 首先管家婆下载地址&#xff1a;http://www.grasp.com.cn/download.aspx?id116 先安装sql server 2008 下载后&#xff0c;运行安装&#xff0c;请注…

《软件工程教程》(第2版) 主编:吴迪 马宏茹 丁万宁 第八章课后习题参考答案

第八章 面向对象技术与UML 课后习题参考答案 一、单项选择题 D &#xff08;2&#xff09;C &#xff08;3&#xff09;B &#xff08;4&#xff09;D &#xff08;5&#xff09;C &#xff08;6&#xff09;B &#xff08;7&#xff09;A &#xff08;8&#xff09;C&…

【LeetCode】343. 整数拆分

343. 整数拆分&#xff08;中等&#xff09; 方法一&#xff1a;数学推导 思路 将数字 n 拆分为若干个数字之和&#xff0c;即 n n1 n2 ... na &#xff0c;本道题等价于求解 max(n1 * n2 * ... * na) &#xff0c;根据数学推导&#xff0c;可以得到两个结论&#xff1a;…

【51单片机】LED点阵屏

&#x1f38a;专栏【51单片机】 &#x1f354;喜欢的诗句&#xff1a;更喜岷山千里雪 三军过后尽开颜。 &#x1f386;音乐分享【Waiting For Love】 大一同学小吉&#xff0c;欢迎并且感谢大家指出我的问题&#x1f970; 目录 &#x1f354;74HC595图片 &#x1f354;74HC59…

多层感知器模型与模型训练

文章目录 1. 多层感知器模型与模型训练1.1 多层感知器模型1.2 损失函数1.3 优化器与初始化模型1.4 编写训练循环1.5 案例代码整合 最近看了日月光华老师的《PyTorch深度学习简明实战》&#xff0c;将里面的代码自己动手复现了一遍&#xff0c;还是受益良多&#xff0c;书里面的…

【Python】狂肝两万字带你学会——类与对象

目录 01-初始对象 生活中的数据组织 程序中的数据组织​编辑 使用对象组织数据 总结01 02-类的成员方法 类的定义和使用 成员变量和成员方法 成员方法的定义语法 注意事项 成员方法——代码演示 总结02 03-类和对象 现实世界的事物和类 类和对象 使用类和对象…

Android 9.0 原生SystemUI下拉通知栏每条通知默认展开

1.前言 在9.0的系统rom原生开发中,在产品对SystemUI下拉通知栏做定制的时候,在下拉状态栏的时候,通知栏中 最后一条通知默认是收缩的 点击按钮 就会展开 原生系统systemui就是如此,为了更美观 所以要求最后一条通知也默认展开,显得更美观 最终效果图: 2.原生SystemUI下拉通…

网络通信原理

网络通信原理目录 1.网络通信基础1.1 IP地址1.2 端口号 2. 通信协议2.1 协议简介2.1 协议分层 3. 封装和分用 1.网络通信基础 &#x1f604;网络通信的目的是网络数据传输&#xff0c;是主机的不同进程间&#xff0c;基于网络实现的数据传输。那么&#xff0c;首先我们应该先弄…

Java实现调用外部程序

Java实现调用外部程序 Java库Runtime类与ProcessBuilder类参数传递执行结果Runtime类的使用ProcessBuilder类的使用无参数调用简单参数调用复杂参数调用 Apache Commons Exec库使用步骤介绍使用实例 Java库 在Java中&#xff0c;可以通过Runtime类或ProcessBuilder类来实现调用…

看看人家的MyBatis批量插入数据优化,从120s到2.5s,那叫一个优雅!

粗略的实验 最后 最近在压测一批接口的时候&#xff0c;我发现接口处理速度比我们预期的要慢。这让我感到有点奇怪&#xff0c;因为我们之前已经对这些接口进行了优化。但是&#xff0c;当我们进行排查时&#xff0c;发现问题出在数据库批量保存这块。 我们的项目使用了 myb…

开源小项目ChatGPT-website已获得100+star,我都干了什么

&#x1f4cb; 个人简介 &#x1f496; 作者简介&#xff1a;大家好&#xff0c;我是阿牛&#xff0c;全栈领域优质创作者。&#x1f61c;&#x1f4dd; 个人主页&#xff1a;馆主阿牛&#x1f525;&#x1f389; 支持我&#xff1a;点赞&#x1f44d;收藏⭐️留言&#x1f4d…

微信小程序学习实录1(wxml文档、引入weui、双向数据绑定、提交表单到后端)

微信小程序学习实录 一、wxml文档二、新建页面快捷方式三、微信小程序引入weui四、双向数据绑定1.wxml渲染层2.js逻辑层 提交表单到后端五、微信小程序跳转到H5 一、wxml文档 <!-- index.wxml --> <view><!-- 数据绑定 --><view><text>{{name}}…

蛋白质界的 ChatGPT:AlphaFold2 论文必备知识,不会有人还不知道吧

你知道 AlphaFold2 吗&#xff1f;它真正解决了蛋白质三维结构预测的算法困境&#xff0c;堪称蛋白质界的 chat-GPT4&#xff0c;甚至它的意义不是 chat-GPT4 所能够匹敌的。它为世界疾病治疗药物开发以及探究生物生命之谜提供了通向天神的一条道路&#xff0c;未来是生物的世纪…

Java 基础入门篇(二)—— Java 基础语法

文章目录 一、注释二、字面量三、变量3.1 变量概述3.2 变量在计算机中的底层原理 四、数据类型五、关键字、标志符六、类型转换6.1 自动类型转换6.2 表达式的自动类型转换6.3 强制类型转换 七、运算符7.1 基本算数运算符7.2 符号做连接符7.3 自增自减运算符7.4 赋值运算符7.5 …

Java 基础入门篇(五)—— 面向对象编程

文章目录 一、面向对象的思想二、类的定义与对象的创建三、对象内存分配情况 ★ 3.1 两个对象的内存图3.2 两个变量指向同一个对象内存图 四、构造器4.1 构造器的格式与分类4.2 构造器的调用 五、 this 关键字六、封装七、标准JavaBean补充&#xff1a;局部变量和成员变量的区别…

Java 基础入门篇(六)—— String 类详解

文章目录 一、String 类概述二、String 创建对象的方式2.1 创建对象的两种方式2.2 面试&#xff1a;两种方式的区别 ★2.3 常见面试题 ★ 三、String 类常用方法3.1 字符串内容比较3.2 常用 API&#xff1a;遍历、截取、替换、分割 一、String 类概述 java.lang.String 类代表…

Java 基础入门篇(四)—— 方法的重载与参数传递机制

文章目录 一、方法的定义二、方法的参数传递机制 ★2.1 基本类型的参数传递2.2 引用类型的参数传递 三、方法重载 一、方法的定义 方法的作用&#xff1a;封装一段代码的语法结构&#xff0c;可以被重复调用&#xff0c;以此提高代码的复用性&#xff0c;提高开发效率&#xf…

【VsCode远程开发】Windows SSH远程连接Linux服务器 - 无公网IP内网穿透

文章目录 前言视频教程1、安装OpenSSH2、vscode配置ssh3. 局域网测试连接远程服务器4. 公网远程连接4.1 ubuntu安装cpolar内网穿透4.2 创建隧道映射4.3 测试公网远程连接 5. 配置固定TCP端口地址5.1 保留一个固定TCP端口地址5.2 配置固定TCP端口地址5.3 测试固定公网地址远程 转…

Java 基础进阶篇(一)—— static 静态关键字与单例模式

文章目录 一、static 静态关键字1.1 静态成员变量与实例成员变量1.2 静态成员方法与实例成员方法1.3 static 访问注意事项1.4 内存使用情况 二、工具类三、代码块四、单例模式4.1 饿汉单例4.2 懒汉单例 一、static 静态关键字 static&#xff1a;代表静态的意思&#xff0c;可…