Maven必知的7个问题,你会吗?

点击上方“Java中文社群”,选择“设为星标”

终身学习者,以编程为乐!

原文:https://www.jianshu.com/p/20b39ab6a88c

在如今的互联网项目开发当中,特别是Java领域,可以说Maven随处可见。Maven的仓库管理、依赖管理、继承和聚合等特性为项目的构建提供了一整套完善的解决方案,可以说如果你搞不懂Maven,那么一个多模块的项目足以让你头疼,依赖冲突就会让你不知所措,甚至搞不清楚项目是如何运行起来的.....OK,博主就曾经被Maven“伤害”过,那么该专题的目的就是:彻底搞定Maven!

回想一下,当你新到一家公司,安装完JDK后就会安装配置Maven(MAVEN_HOME、path),很大可能性你需要修改settings.xml文件,比如你会修改本地仓库地址路径,比如你很可能会copy一段配置到你的settings.xml中(很可能就是私服的一些配置)。接下来,你会到IDEA或者Eclipse中进行Maven插件配置,然后你就可以在工程中的pom.xml里面开始添加<dependency>标签来管理jar包,在Maven规范的目录结构下进行编写代码,最后你会通过插件的方式来进行测试、打包(jar or war)、部署、运行。

上面描述了我们对Maven的一些使用方式,下面我们进行一些思考:

1、本地仓库?Maven到底有哪些仓库?它们什么关系?

Maven仓库:

本地仓库路径配置:

你要jar包,不可能每次都要联网去下载吧,多费劲,所以本地仓库就是相当于加了一层jar包缓存,先到这里来查。如果这里查不到,那么就去私服上找,如果私服也找不到,那么去中央仓库去找,找到jar后,会把jar的信息同步到私服和本地仓库中。

私服,就是公司内部局域网的一台服务器而已,你想一下,当你的工程Project-A依赖别人的Project-B的接口,怎么做呢?没有Maven的时候,当然是copy Project-B jar到你的本地lib中引入,那么Maven的方式,很显然需要其他人把Project-B deploy到私服仓库中供你使用。因此私服中存储了本公司的内部专用的jar!不仅如此,私服还充当了中央仓库的镜像,说白了就是一个代理!

中央仓库:该仓库存储了互联网上的jar,由Maven团队来维护,地址是:http://repo1.maven.org/maven2/。

2、关于<dependency>的使用

依赖管理:

其实这个标签揭示了jar的查找坐标:groupIdartifactIdversion

一般而言,我们可以到私服上输入artifactId进行搜索,或者到http://search.maven.org/、http://mvnrepository.com/上进行查找确定坐标。

version分为开发版本(Snapshot)和发布版本(Release),那么为什么要分呢?

在实际开发中,我们经常遇到这样的场景,比如A服务依赖于B服务,A和B同时开发,B在开发中发现了BUG,修改后,将版本由1.0升级为2.0,那么A必须也跟着在POM.XML中进行版本升级。过了几天后,B又发现了问题,进行修改后升级版本发布,然后通知A进行升级...可以说这是开发过程中的版本不稳定导致了这样的问题。

Maven,已经替我们想好了解决方案,就是使用Snapshot版本,在开发过程中B发布的版本标志为Snapshot版本,A进行依赖的时候选择Snapshot版本,那么每次B发布的话,会在私服仓库中,形成带有时间戳的Snapshot版本,而A构建的时候会自动下载B最新时间戳的Snapshot版本!

3、既然Maven进行了依赖管理,为什么还会出现依赖冲突?处理依赖冲突的手段是?

依赖的版本?

首先来说,对于Maven而言,同一个groupId同一个artifactId下,只能使用一个version

根据上图的依赖顺序,将使用1.2版本的jar。

现在,我们可以思考下了,比如工程中需要引入A、B,而A依赖1.0版本的C,B依赖2.0版本的C,那么问题来了,C使用的版本将由引入A、B的顺序而定?这显然不靠谱!如果A的依赖写在B的依赖后面,将意味着最后引入的是1.0版本的C,很可能在运行阶段出现类(ClassNotFoundException)、方法(NoSuchMethodError)找不到的错误(因为B使用的是高版本的C)!

这里其实涉及到了2个概念:依赖传递(transitive)、Maven的最近依赖策略。

依赖传递:如果A依赖B,B依赖C,那么引入A,意味着B和C都会被引入。

Maven的最近依赖策略:如果一个项目依赖相同的groupId、artifactId的多个版本,那么在依赖树(mvn dependency:tree)中离项目最近的那个版本将会被使用。(从这里可以看出Maven是不是有点小问题呢?能不能选择高版本的进行依赖么?据了解,Gradle就是version+策略)

现在,我们可以想想如何处理依赖冲突呢?

想法1:要使用哪个版本,我们是清楚的,那么能不能不管如何依赖传递,都可以进行版本锁定呢?

使用<dependencyManagement>  [这种主要用于子模块的版本一致性中]

想法2:在依赖传递中,能不能去掉我们不想依赖的?

使用<exclusions> [在实际中我们可以在IDEA中直接利用插件帮助我们生成]

想法3:既然是最近依赖策略,那么我们就直接使用显式依赖指定版本,那不就是最靠近项目的么?

使用<dependency>

4、引入依赖的最佳实践,提前发现问题!

在工程中,我们避免不了需要加一些依赖,也许加了依赖后运行时才发现存在依赖冲突在去解决,似乎有点晚!那么能不能提前发现问题呢?

如果我们新加入一个依赖的话,那么先通过mvn dependency:tree命令形成依赖树,看看我们新加入的依赖,是否存在传递依赖,传递依赖中是否和依赖树中的版本存在冲突,如果存在多个版本冲突,利用上文的方式进行解决!

5、Maven规范化目录结构

这里需要注意2点:

第一:src/main下内容最终会打包到Jar/War中,而src/test下是测试内容,并不会打包进去。

第二:src/main/resources中的资源文件会COPY至目标目录,这是Maven的默认生命周期中的一个规定动作。(想一想,hibernate/mybatis的映射XML需要放入resources下,而不能在放在其他地方了)

6、Maven的生命周期

Maven生命周期:

我们只需要注意一点:执行后面的命令时,前面的命令自动得到执行。

实际上,我们最常用的就是这么几个:

clean:有问题,多清理!

package:打成Jar or War包,会自动进行clean+compile

install:将本地工程Jar上传到本地仓库

deploy:上传到私服

7、关于scope依赖范围

既然,Maven的生命周期存在编译、测试、运行这些过程,那么显然有些依赖只用于测试,比如junit;有些依赖编译用不到,只有运行的时候才能用到,比如mysql的驱动包在编译期就用不到(编译期用的是JDBC接口),而是在运行时用到的;还有些依赖,编译期要用到,而运行期不需要提供,因为有些容器已经提供了,比如servlet-api在tomcat中已经提供了,我们只需要的是编译期提供而已。

scope 取值如下:

compile:默认的scope,运行期有效,需要打入包中。

provided:编译期有效,运行期不需要提供,不会打入包中。

runtime:编译不需要,在运行期有效,需要导入包中。(接口与实现分离)

test:测试需要,不会打入包中。

system:非本地仓库引入、存在系统的某个路径下的jar。(一般不使用)


【END】

关注下方二维码,订阅更多精彩内容

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

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

相关文章

Linux 小知识翻译 - 「Linux的吉祥物企鹅叫什么名字?」

这次说说Linux的吉祥物 *企鹅* 都知道Linux的吉祥物是企鹅&#xff0c;但是这个企鹅叫什么名字呢&#xff1f; 它的名字就是「Tux」&#xff0c;注意可不是「Tax」(税收)。 具体参考 wiki&#xff1a;中文解释 英文的解释更为详细一些&#xff1a;英文解释 Linux内核发展到 v2…

WordPress修改WordPress地址和站点地址之后无法打开网站和无法后台登录

WordPress地址一定不要修改。 WordPress修改WordPress地址和站点地址之后无法打开网站和无法后台登录的解决方法&#xff1a; 1、使用ssh登录服务器 xshell、SecureCRT等工具均可。 2、登录MySQL数据库 使用如下指令后&#xff0c;输入密码&#xff0c;打开mysql数据库&am…

从JVM入手,聊聊Java的学习和复习!

我们在学习的时候&#xff0c;经常会遇到这样一个问题&#xff1a;「学完就忘」这个问题大部分人都会遇到&#xff0c;那么我们今天就来聊聊&#xff0c;为啥会学了就忘呢&#xff1f;我根据自己的学习经验&#xff0c;大致总结以下三点原因&#xff1a;1、知识没有用起来2、没…

Activity和Service交互

2019独角兽企业重金招聘Python工程师标准>>> As discussed in the Services document, you can create a service that is both started and bound. That is, the service can be started by calling startService(), which allows the service to run indefinitely…

Redis从入门到精通|干货篇

点击上方“Java中文社群”&#xff0c;选择“设为星标”终身学习者&#xff0c;以编程为乐&#xff01;来源&#xff1a;http://rrd.me/eDY9S常用的 SQL 数据库的数据都是存在磁盘中的&#xff0c;虽然在数据库底层也做了对应的缓存来减少数据库的 IO 压力。由于数据库的缓存一…

最重要的7个Drupal内核模板文件

Drupal内核拥有40多个模板文件&#xff0c;其中最重要的有7个。它们组成了页面的主要部分&#xff0c;在定制Drupal主题时经常要用到。因此列表如下供大家参考。 模板名原始位置用途html.tpl.phpmodules/system打印HTML文档的结构。包括了<head>标记中的内容&#xff0c;…

Java中的13个原子操作类

点击上方“Java中文社群”&#xff0c;选择“设为星标”终身学习者&#xff0c;以编程为乐&#xff01;来源&#xff1a;https://www.iteye.com/blog/xiaoheng-2509522atomic 包中的 13 个类&#xff0c;属于 4 中类型的原子更新方式.原子更新基本类型原子更新数组原子更新引用…

Redis中的键值过期操作

1.过期设置 Redis 中设置过期时间主要通过以下四种方式&#xff1a; expire key seconds&#xff1a;设置 key 在 n 秒后过期&#xff1b;pexpire key milliseconds&#xff1a;设置 key 在 n 毫秒后过期&#xff1b;expireat key timestamp&#xff1a;设置 key 在某个时间戳…

天意PE维护系统 V2021.7.16版

天意PE U盘维护系统是一款用于系统维护和装机的U盘PE系统&#xff08;U盘启动盘&#xff09;&#xff0c;采用双PE模式,支持UEFI双启动&#xff0c;集成常用工具的维护软件&#xff0c;集成SRS驱动&#xff0c;新版更加上了NVME硬盘的支持&#xff0c;天意U盘维护系统纯净、稳定…

Redis持久化的几种方式——深入解析RDB

Redis 的读写都是在内存中&#xff0c;所以它的性能较高&#xff0c;但在内存中的数据会随着服务器的重启而丢失&#xff0c;为了保证数据不丢失&#xff0c;我们需要将内存中的数据存储到磁盘&#xff0c;以便 Redis 重启时能够从磁盘中恢复原有的数据&#xff0c;而整个过程就…

【LeetCode】148. Sort List

Sort List Sort a linked list in O(n log n) time using constant space complexity. 要求时间复杂度为O(nlogn)&#xff0c;那么不能用quickSort了&#xff08;最坏O(n^2)&#xff09;&#xff0c;所以使用mergeSort. 通常写排序算法都是基于数组的&#xff0c;这题要求基于链…

WordPress网站搬家教程(根目录程序+ MySQL数据库)

WordPress博客网站怎么搬家到新的服务器上&#xff1f;WordPress搬家无非是两点&#xff0c;即WP程序文件和数据库&#xff0c;具体什么系统不用考虑&#xff1a; 3分钟详解WordPress搬家教程 本文新手站长网关于WordPress搬家教程是帮大家缕清思路&#xff08;参考&#xff1…

Redis持久化的几种方式——RDB深入解析

点击上方“Java中文社群”&#xff0c;选择“设为星标”终身学习者&#xff0c;以编程为乐&#xff01;Redis 的读写都是在内存中&#xff0c;所以它的性能较高&#xff0c;但在内存中的数据会随着服务器的重启而丢失&#xff0c;为了保证数据不丢失&#xff0c;我们需要将内存…

配置Debian11服务器允许root用户远程SSH登录

全新安装系统后&#xff0c;默认情况下将禁用Debian Linux上的root登录。当您尝试以root用户身份登录Debian11 Linux服务器时&#xff0c;访问将被拒绝。要在Debian Linux系统上为root用户启用SSH登录&#xff0c;您需要首先配置SSH服务器。 0.首先安装SSH 注意&#xff1a;如…

带你深入浅出的分析 HashTable 源码

Hashtable 一个元老级的集合类&#xff0c;早在 JDK 1.0 就诞生了&#xff0c;今天小编想和大家一起来揭开它的面纱&#xff01;01、摘要在集合系列的第一章&#xff0c;咱们了解到&#xff0c;Map 的实现类有 HashMap、LinkedHashMap、TreeMap、IdentityHashMap、WeakHashMap、…

Debian11服务器系统默认不存在sudo命令的解决办法

1.切换到root用户&#xff0c;安装vim&#xff0c;修改镜像源文件 apt-get install vim vim /etc/apt/sources.list注释掉原有的内容&#xff0c;添加如下阿里云的镜像源 deb http://mirrors.aliyun.com/debian/ bullseye main contrib deb-src http://mirrors.aliyun.com/…

Redis使用不当导致应用卡死

作者&#xff1a;小木来源&#xff1a;http://rrd.me/ezfTj首先说下问题现象&#xff1a;内网sandbox环境API持续1周出现应用卡死&#xff0c;所有api无响应现象刚开始当测试抱怨环境响应慢的时候 &#xff0c;我们重启一下应用&#xff0c;应用恢复正常&#xff0c;于是没做处…

阿里巴巴Linux开源镜像站 华为Linux开源镜像站 Linux宝塔面板

学习Linux系统和用Linux系统作服务器时&#xff0c;推荐Linux从Linux系统开源镜像站下载&#xff0c;国内源下载速度快&#xff0c;Linux系统可选择方案多&#xff01; 1.阿里巴巴开源镜像站&#xff1a; https://developer.aliyun.com/mirror/ 2.华为开源镜像站&#xff1a; …

阿里Java开发手册——如何优化数据库?

作者&#xff1a;杨冠宝/高海慧来自&#xff1a;码出高效 Java 开发手册数据库作为服务器端最为最为昂贵的资源之一&#xff0c;如果使用不当常常会导致系统卡顿或系统崩溃&#xff0c;那如何来优化数据库呢&#xff1f;下面来看阿里巴巴《Java开发手册》给出的优化方案。1 建立…

虚拟机VMware Workstation安装Linux服务器Debian11系统详细教程

虚拟机VMware Workstation安装Linux服务器Debian11系统详细教程如下&#xff1a; 准备好&#xff1a; 1.安装好虚拟机VMware Workstation 2.从Linux开源镜像下载的debian11镜像系统 从创建新的虚拟机开始 安装完系统重启进入系统&#xff0c;首先要做的是更新为阿里云的…