本文摘自:https://dwz.cn/PHYFFK27
Maven的仓库管理、依赖管理、继承和聚合等特性为项目的构建提供了一整套完善的解决方案,如果你搞不懂Maven,那么一个多模块的项目足以让你头疼,依赖冲突就会让你不知所措,甚至搞不清楚项目是如何运行起来的...OK,博主就曾经被Maven“伤害”过,所以,我们要:彻底搞定Maven!回想一下,当你新到一家公司,安装完JDK后就会安装配置Maven,很大可能性你需要修改settings.xml文件,比如你会修改本地仓库地址路径,比如你很可能会copy一段配置到你的settings.xml中(很可能就是私服的一些配置)。接下来,你会到IDEA或者Eclipse中进行Maven插件配置,然后你就可以在工程中的pom.xml里面开始添加标签来管理jar包,在Maven规范的目录结构下进行编写代码,最后你会通过插件的方式来进行测试、打包(jar or war)、部署、运行。上面描述了对Maven的一些使用方式,下面我们进行一些思考:
1、本地仓库?Maven到底有哪些仓库?它们什么关系?
Maven仓库:

2、关于 <dependency>
的使用
依赖管理:
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点:1、src/main下内容最终会打包到Jar/War中,而src/test下是测试内容,并不会打包进去。2、src/main/resources中的资源文件会COPY至目标目录,这是Maven的默认生命周期中的一个规定动作。(想一想,hibernate/mybatis的映射XML需要放入resources下,而不能在放在其他地方了)
6、Maven的生命周期
Maven生命周期:
我们只需要注意一点:执行后面的命令时,前面的命令自动得到执行。实际上,我们最常用的就是这么几个:1、clean:有问题,多清理!2、package:打成Jar or War包,会自动进行clean+compile3、install:将本地工程Jar上传到本地仓库4、deploy:上传到私服