Maven虐我千百遍,我待Maven如初恋
前言
在如今的互联网项目开发当中,特别是Java领域,可以说Maven随处可见。Maven的仓库管理、依赖管理、继承和聚合等特性为项目的构建提供了一整套完善的解决方案,可以说如果你搞不懂Maven,那么一个多模块的项目足以让你头疼,依赖冲突就会让你不知所措,甚至搞不清楚项目是如何运行起来的,专题的目的就是:彻底搞定Maven!
Thinking in Maven
Maven的使用方式
Maven的架构
Maven仓库配置
<!-- localRepository| The path to the local repository maven will use to store artifacts.|| Default: ${user.home}/.m2/repository --> <localRepository>/path/to/local/repo</localRepository>
你要jar包,不可能每次都要联网去下载吧,多费劲,所以本地仓库就是相当于加了一层jar包缓存,先到这里来查。如果这里查不到,那么就去私服上找,如果私服也找不到,那么去中央仓库去找,找到jar后,会把jar的信息同步到私服和本地仓库中。
- 私服,就是公司内部局域网的一台服务器而已,你想一下,当你的工程Project-A依赖别人的Project-B的接口,怎么做呢?没有Maven的时候,当然是copy Project-B jar到你的本地lib中引入,那么Maven的方式,很显然需要其他人把Project-B deploy到私服仓库中供你使用。因为私服中存储了本公司的内部专用的jar!不仅如此,私服还充当了中央仓库的镜像,说白了就是一个代理!
- 中央仓库:由Maven团队来维护,地址是:http://repo1.maven.org/maven2/。
依赖的使用
坐标配置
<dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.12.6</version> </dependency>
依赖管理 :groupId、artifactId、version
一般而言,我们可以到私服上输入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版本!
为什么会出现依赖冲突?如何解决冲突?
场景假设
首先来说,对于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>
Maven最佳实践
在工程中,我们避免不了需要加一些依赖,也许加了依赖后运行时才发现存在依赖冲突在去解决,似乎有点晚!那么能不能提前发现问题呢?
如果我们新加入一个依赖的话,那么先通过mvn dependency:tree命令形成依赖树,看看我们新加入的依赖,是否存在传递依赖,传递依赖中是否和依赖树中的版本存在冲突,如果存在多个版本冲突,利用上文的方式进行解决!
Maven目录结构
这里需要注意2点:
- 第一:src/main下内容最终会打包到Jar/War中,而src/test下是测试内容,并不会打包进去。
- 第二:src/main/resources中的资源文件会COPY至目标目录,这是Maven的默认生命周期中的一个规定动作。(想一想,hibernate/mybatis的映射XML需要放入resources下,而不能在放在其他地方了)
Maven的生命周期
我们只需要注意一点:执行后面的命令时,前面的命令自动得到执行。
- clean:有问题,多清理!
- package:打成Jar or War包,会自动进行clean+compile
- install:将本地工程Jar上传到本地仓库
- deploy:上传到私服
scope依赖范围
既然,Maven的生命周期存在编译、测试、运行这些过程,那么显然有些依赖只用于测试,比如junit;有些依赖编译用不到,只有运行的时候才能用到,比如mysql的驱动包在编译期就用不到(编译期用的是JDBC接口),而是在运行时用到的;还有些依赖,编译期要用到,而运行期不需要提供,因为有些容器已经提供了,比如servlet-api在tomcat中已经提供了,我们只需要的是编译期提供而已。
- compile:默认的scope,运行期有效,需要打入包中。
- provided:编译期有效,运行期不需要提供,不会打入包中。
- runtime:编译不需要,在运行期有效,需要导入包中。(接口与实现分离)
- test:测试需要,不会打入包中。
- system:非本地仓库引入、存在系统的某个路径下的jar。(一般不使用)
转载于:https://www.cnblogs.com/mengxinrenyu/p/11004027.html
Maven虐我千百遍,我待Maven如初恋相关推荐
- Maven 虐我千百遍,我待 Maven 如初恋 侵删
前言 在如今的互联网项目开发当中,特别是Java领域,可以说Maven随处可见.Maven的仓库管理.依赖管理.继承和聚合等特性为项目的构建提供了一整套完善的解决方案,可以说如果你搞不懂Maven,那 ...
- Maven虐我千百遍,我待Maven如初恋!
来源 | 张丰哲 jianshu.com/p/20b39ab6a88c 互联网开发,特别Java领域,可以说Maven随处可见.Maven的仓库管理.依赖管理.继承和聚合等特性为项目构建提供了一整套完 ...
- Maven 虐我千百遍,我待 Maven 如初恋
前言 在如今的互联网项目开发当中,特别是Java领域,可以说Maven随处可见.Maven的仓库管理.依赖管理.继承和聚合等特性为项目的构建提供了一整套完善的解决方案,可以说如果你搞不懂Maven,那 ...
- 我虐小车千百遍,小车待我如初恋
None 转.转.转,转它个天昏地暗. 卓大大,来调侃下.****这轮胎能比赛吗? 无语 大哥,拐弯悠着点.****一脚油门,车毁人亡. 我是车模中的白马王子
- Recycleview 虐我千百遍 我待Recycleview如初恋
Recycleview(一) 第二天正式入门android,还以为门槛刚迈进去,谁知道我连鞋都还没脱呢,第一次接触Recycleview,直接懵逼,写一些源代码以防自己忘记 第一步 新建一个包 -ad ...
- Netty虐我千百遍我待Netty如初恋
段一 刚开始接触Netty时, 主要是通过浏览文章, 好的差的统统浏览, 慢慢的也就会发现几个好的博主, 包括他们录播的视频我也会去看. 甚至还买了书籍, 不求甚解的看, 反正就是多看吸收. 一开始还 ...
- VMware虐我千百遍,我却待她如初恋
文章目录 一.相关环境 1.操作系统 2.VMware版本 二.我遇到过的bug 1.VMCI驱动程序无法自动安装,需要手动安装 2.Vmware提示以独占方式锁定此配置文件失败 3.VMware提示 ...
- 算法虐我千百遍,我待算法如初恋
转自:算法虐我千百遍,我待算法如初恋 算法虐我千百遍,我待算法如初恋. 学习方法 1) 把所有经典算法写一遍 2) 看算法源码 3) 加入算法学习社区,相互鼓励学习 4) 看经典书籍 基本数据 ...
- 那些曾虐我千百遍的计算机组成原理
那些曾虐我千百遍的计算机组成原理 本笔记知识点来源于b站狂神说:聊汇编先导课,有兴趣的小伙伴点这里:狂神聊汇编先导课 文章目录 那些曾虐我千百遍的计算机组成原理 进制的本质 有符号数和无符号数的区别 ...
最新文章
- html调用asp边疆,[求助]怎么实现ASP在HTML中调用
- std::ref std::cref
- C#中(int),int.Parse,int.TryParse,Convert.ToInt32四则之间的用法
- @async 没有异步_javascript之异步函数
- 2018-3-10 unset 变量 ab测试
- 《构建高可用Linux服务器 第3版》—— 2.7 系统维护时应注意的非技术因素
- CTRL-Space always toggles Chinese IME (Windows 7、10)
- 原版98启动盘镜像.img_【教程】利用Windows 10 官方下载工具下载最新系统镜像、制作启动盘...
- 彗星撞地球-Warez组织的经典力作(15G动画压缩成64Kb的那个,2004年的第一名)
- 大数据架构与技术——(一)大数据概述
- 聚焦存储即平台,浪潮存储迎来发展新机遇
- 设计师如何摆脱设计思维的局限
- (转载)酷炫桌面背景图片,实用命令图片
- 关于C/C++中的short类型
- java设计功能怎么实现代码_Java中的门面设计模式及如何用代码实现
- 爬虫python代码网易云_使用python爬取网易云歌曲下载时为0KB的解决方法 | ZPY博客...
- 腾讯产品总监曹菲:产品经理们,五年后,你会失业吗? 【上】
- MySQL图形管理软件安装及使用
- AIDA64内存与缓存测试过了算稳定吗_机电厂家安钛克也出RGB内存了?那么用起来究竟如何?...
- 如何评价网络的好坏及IP相关知识
热门文章
- 一个更优的零知识证明:Bulletproofs
- android settings源代码分析(3)
- Android HTTP必知必会
- JZOJ 5484. 【清华集训2017模拟11.26】快乐树
- python中的模块原则_python 的模块与包
- 当复选框中打勾时后面自动显示y或者n_基于轮廓系数确定K-Means聚类中的K
- smartdraw 2008 成功安装
- 2020-07-09 CVPR2020 VL论文讨论(4) 笔记
- 2007年分区联赛提高组之一 统计数字
- POJ 3250 Bad Hair Day (单调栈)