Maven的坐标用来惟一标示一个项目在Maven仓库的位置,Maven的坐标主要由groupId、artifactId、version、packaging、classifier 5个元素组成,其中groupId、artifactId、version是必要的元素,而packaging、classifier能够省略。java
groupId:定义当前项目所属的项目包,对应了Maven仓库中的目录结构spring
artifactId:通常为当前项目名称,对应了项目名称目录名sql
version:项目的版本,对应了版本目录名数据库
packaging:指定打包的方式,默认为jar包,可选(war、maven-plugin、pom、zip等)api
classifier:用于帮助定义构建输出的一些附属构建,不能直接定义一般有插件帮助生成maven
当使用坐标去maven仓库中找寻依赖文件时,将会使用如下路径查找:ide
$RESPORITY_HOME/groupId(replace . to /)/artifactId/version/artifactId-version[-classifier].packaging (当packaging为maven-plugin时扩展名也为jar)工具
当version为SNAPSHOT(快照)版本,发布到远程仓库,SNAPSHOT会被替换成当时的时间戳,当在被依赖时,会时间最近时间戳的版本测试
Maven的pom文件中配置依赖大体包含下面的元素:spa
<dependency> <groupId></groupId> <artifactId></artifactId> <version></version> <type></type> <scope></scope> <optional></optional> <exclusions> <exclusion></exclusion> </exclusions> </dependency>
groupId、artifactId、version用来惟一的表示一个构建
type:依赖的类型,对应了项目坐标定义时的packaging,默认为jar
scope:依赖的范围,可选值有compile、test、provided、runtime、system、import
optional:标记依赖是否为可选依赖,默认为false
exclusions:用来排除传递性依赖
compile:编译范围依赖,默认选项,对于编译、测试、运行三个阶段都须要依赖
test:测试范围依赖,只在测试阶段须要用的依赖,如junit
provided:已提供范围依赖,对于编译和测试阶段须要此依赖,当运行期不须要,常见的如servlet-api,运行期容器提供
runtime:运行时范围依赖,对于运行和测试阶段须要此依赖,如JDBC驱动的实现,代码在编译时只须要JDK提供的JDBC接口
system:系统范围依赖,与provided依赖方位同样,只是使用system必须显示的使用systemPath指定依赖文件路径
import:这个依赖范围比较特殊,并不会影响编译、测试、运行三个阶段,是用来复用某个pom文件中配置的dependencyManagement下的配置内容的,因此使用这个scope的dependency必须是知足一些条件才有效:
(1)必须在dependencyManagement元素内
(2)packging必须为pom
当前项目的直接依赖可能也须要依赖其余的jar,这种依赖叫作二级依赖,Maven会使用依赖的传递机制帮咱们处理好二级及以上的依赖,好比以下依赖:
project -> spring-core -> commons-logging
当前项目依赖于spring-core,而spring-core又依赖于commons-logging,咱们并不须要在project的pom文件中显示的申明commons-logging的依赖,Maven会经过spring-core的pom文件最终将commons-logging的依赖加载到project项目中,可是在依赖的传递过程当中也会有必定的范围规则,以下图:
一级依赖\二级依赖 |
compile |
test |
provided |
runtime |
compile |
compile | —— | —— |
runtime |
test |
test |
—— |
—— |
test |
provided |
provided |
—— |
provided |
provided |
runtime |
runtime |
—— |
—— |
runtime |
简而言之就是
当二级依赖的范围是compile时,传递依赖后的方位和一级依赖相同;
当二级依赖的范围是test时,此依赖不会传递;
当二级依赖的范围是provided时,只有一级依赖也为provided才会传递;
当二级依赖的范围是runtime时,除了一级依赖为compile,会传递runtime范围,其他的范围与一级依赖一致
当项目的间接依赖存在相同的项目不一样的版本时,Maven不容许相同的项目被加载屡次,这时候就须要对依赖进行调解,好比:
A->B->C(1.0) ,A->D->C(2.0),A->E->F->C(3.0)
A依赖于B和D和E,但B依赖于C的1.0版本,而D依赖于C的2.0版本,F依赖于C的3.0版本,不可能A中加载三个版本的C,这样作是显然是不对的,因此Maven在遇到这种状况是制定了一个规则来肯定到底加载哪一个版本的C,规则以下:
首先以依赖的深度来选择,浅的优先,因此C(3.0)不可能被加载
在深度相同的状况下,pom文件中先被解析到的优先
上面有提到pom文件中声明依赖时可使用<optional>true</optional>声明该依赖为可选依赖,可选依赖不会被传递,如:
A->B,B->C(可选),B->D(可选)
想上面的C和D都不会被传递,须要在A的pom中明确的声明是使用C仍是D,举个形象的例子,B是一个持久化隔离的工具包,它支持多种数据库,C、D能够看做Mysql的链接包、Oracle的链接包,C、D在B的pom中的依赖声明就是可选的,他们不会被传递给A,在A中须要根据实际使用的数据库,声明使用的链接包