Maven,是一款以项目对象模型(POM)思想为基础的项目管理工具。它包含构建工具和依赖管理工具两部分。
构建工具
Maven构建工具用三套完整的生命周期来定义一个项目构建及发布的过程。
三套完整的生命周期
而每个生命周期又包含了以下几个主要的阶段及其作用
Clean生命周期 对项目进行清理
pre-clean 执行一些清理前需要完成的工作
clean 清理上一次构建生成的文件
post-clean 执行一些清理后需要完成的工作
Default生命周期 对项目进行构建
validate 验证项目是否正确且所有必要信息都是可用的
compile 对源代码进行编译
test 使用适当的单元测试框架进行测试
package 对项目进行打包
install 安装打包的项目到本地仓库中以供其他项目使用
deploy 将打包的项目发送到远程仓库中
Site生命周期 建立项目站点
pre-site 执行一些生成项目站点前需要完成的工作
site 生成项目站点文档
post-site 执行一些在生成项目站点后需要完成的工作
site-deploy 将生成的项目站点发布到服务器
各阶段的执行顺序
每个生命周期中所包含的阶段执行是有顺序的,后面的阶段执行依赖于前面的阶段。例如用户在调用test,那么maven将会从Default生命周期的第一个阶段开始执行,直到test阶段为止。
每套生命周期之间的关系
三套生命周期是相互独立的,例如用户在调用Default生命周期中的test时,maven只会执行Default生命周期中相应的阶段,而不会执行Clean或者Site生命周期中的阶段。
再例如大家在执行最常用的
mvn clean install
时,实际上maven调用的是Clean中的pre-clean、clean阶段以及Default中的validate阶段直到install阶段。
依赖管理工具
maven为我们提供了多模块间依赖关系的管理方法,使得开发者从繁琐的模块依赖管理中脱身出来,通过maven,开发者只需要一个pom文件即可实现对项目依赖关系的管理。
maven中,模块被存放在仓库中。仓库会根据依赖包的各个参数组成一个路径来唯一确定一个依赖包。
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.0.0</version>
</dependency>
上面这个依赖包所对应的路径为orgmybatisspringbootmybatis-spring-boot-starter2.0.0
你将能从仓库的对应路径下发现该依赖包
一个配置较为详细的依赖长这样
<dependency>
<groupId>org.apache.kafka</groupId>
<artifactId>kafka-clients</artifactId>
<version>0.8.2.2</version>
<scope>compile</scope>
<optional>false</optional>
<exclusions>
<exclusion>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
</exclusion>
</exclusions>
</dependency>
其中<scope>标签定义了该依赖的范围,依赖范围有五种
- compile 编译、测试和运行阶段有效 [默认]
- provided 编译、测试阶段有效
- test 测试阶段有效
- runtime 运行阶段有效
- system 编译、测试阶段有效。使用该范围的依赖时必须通过systemPath元素显示地指定依赖文件的路径,不依赖Maven仓库解析,所以可能会造成建构的不可移植,因此需要谨慎使用。
<exclusion>标签用于排除该依赖中的某个传递依赖(传递依赖后续将会讲到)。
<optional>标签则用于表示该依赖是否为可选依赖,默认为false。若A依赖B且配置中将B设置为了可选依赖,当项目C引入A作为依赖且C不会用到A依赖B部分的代码,那么C在打包时将不会将B作为依赖导入。
传递依赖
maven中依赖会进行传递。若项目A依赖了B,且B依赖了C。那么当项目G引入A作为依赖时,B和C也会成为G的依赖,这种现象就叫做传递依赖。
正是如此,传递依赖会带来依赖版本冲突的问题,有可能项目会在不自知的情况下依赖了同一个依赖包的多个版本。面对这一现象,maven有两大原则进行依赖版本冲突处理:
- 最短路径优先
最短路径优先
当同一依赖的多个版本被依赖时,优先选择路径更短的版本。上图例子中将会选择C依赖的3.3版本。
- 第一声明优先
第一声明优先
当同一依赖的多个版本被依赖且两个版本号路径长度相等时,优先选择先被依赖的版本号。上图例子中C依赖的两个版本虽然路径长度相等,但2.0版本比3.0版本先被依赖,因此maven会选择使用C依赖的2.0版本。
仓库
仓库分为本地仓库、远程仓库和中央仓库。maven在依赖搜索时会按照顺序依次在各个仓库中进行搜索。
中央仓库和远程仓库有什么区别?实质上,中央仓库是一个特殊的远程仓库。
镜像,最主要的作用就是用来提速,开发者可以通过配置镜像仓库来替代对应的仓库,从而实现提速。
镜像仓库的配置方式如下
<mirrors>
<mirror>
<id>alimaven</id>
<name>aliyun maven</name>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
<mirrorOf>central</mirrorOf>
</mirror>
</mirrors>
其中<mirrorOf>标签表示镜像仓库的覆盖范围,上面例子表示该镜像只替换中央仓库,若你把central替换成*,该镜像将会覆盖所有类型的仓库。