3.1 坐标
不论是本地仓库,还是中央仓库,都会存在很多的构件,比如jar和war等等的。在如此众多的构件中,就是通过groupId,artifactId,version,packaging和classifier来唯一标识一个构件,也就是maven坐标.
-
groupId:定义当前 Maven 项目所属的实际项目,跟 Java 包名类似,通常与域名反向一一对应。
-
artifactId:定义当前 Maven 项目的一个模块,默认情况下,Maven 生成的jar,其文件名会以 artifactId 开头,如 hibernate-core-3.6.5.Final.jar。
-
version:定义项目版本。
-
packaging:定义项目打包方式,如 jar,war,pom,zip ……,默认为 jar。
-
classifier:定义项目的附属构件, hibernate-core-3.6.6.Final-sources.jar,hibernate-core-3.6.6.Final-javadoc.jar,其中 sources 和 javadoc 就是这两个附属构件的 classifier。classifier 不能直接定义,通常由附加的插件帮助生成.
同一个项目,groupId,version会一样,只是artifactId不一样. 现在已经很清楚maven坐标是怎么回事了吧,要特别注意项目和依赖等所有构件在maven中都是由这几个坐标元素所唯一标识。有一些网上的仓库提供了坐标的查询:
http://mvnrepository.com/ |
---|
http://www.sonatype.org/nexus/ |
3.2 依赖包的查询
-
所有的依赖都是通过坐标来进行管理的(GAV—>groupId,artifactId,version)
-
通过设置依赖
-
Maven是如何搜索依赖的?首先会在本地仓库查询,如果本地仓库没有,就去中央仓库查询。
3.3 依赖的范围
先来看看maven项目构建的过程是怎样的:
由上图可知,maven构建项目的主要过程是编译,测试和部署运行。而每一个过程是需要依赖一些jar才能完成的,这个大家都知道,java源代码不可能裸奔,必须有一些基础的类库才行。但是java是怎么能够找到这些类库或者说依赖的jar来支持每一步的运行呢?浅显的理解就是,JVM会首先去检查系统的环境变量,去类路径classpath下去找这些jar。所以我们必需把项目不同运行时期需要的jar等构件放入类路径.
特别要注意:
并不是所有的构件一旦加载进类路径就一直存在于类路径的,因为maven不同的运行时期时加载进类路径的一些构件,这些只是暂存其中的,也把暂存一些构件的类路径称为临时类路径。每个运行时期一旦结束这个临时类路径里面的构件就会被清除。这个对于maven来说,则为依赖范围scope,这个依赖范围是可以被配置的,也就决定了构件在类路径存在的时间范围。
maven依赖范围:
-
compile:编译范围,指 A 在编译时依赖 B,此范围为默认依赖范围。编译范围的依赖会用在 编译、测试、运行,由于运行时需要所以编译范围的依赖会被打包。
-
provided:provided 依赖只有在当 JDK 或者一个容器已提供该依赖之后才使用, provided 依赖在编译和测试时需要,在运行时不需要,比如:servlet api 被 tomcat 容器提供。
-
runtime:runtime 依赖在运行和测试系统的时候需要,但在编译的时候不需要。比如:jdbc 的驱动包。由于运行时需要所以 runtime 范围的依赖会被打包。
-
test:test 范围依赖 在编译和运行时都不需要,它们只有在测试编译和测试运行阶段可用, 比如:junit。由于运行时不需要所以 test范围依赖不会被打包。
-
system:system 范围依赖与 provided 类似,但是你必须显式的提供一个对于本地系统中 JAR 文件的路径,需要指定 systemPath 磁盘路径,system依赖不推荐使用。
总结:
默认引入 的 jar 包 ------- compile 【默认范围 可以不写】(编译、测试、运行 都有效 )
servlet-api 、jsp-api ------- provided (编译、测试 有效, 运行时无效 防止和 tomcat 下 jar 冲突)
jdbc 驱动 jar 包 ---- runtime (测试、运行 有效 )
junit ----- test (测试有效)
依赖范围由强到弱的顺序是:compile>provided>runtime>test
默认的依赖的范围是:compile
3.4 依赖会被传递
当我A模块依赖于B模块,而B模块依赖于C模块,那么A模块也就间接的依赖于C模块,这种依赖主要是基于complie范围(编译范围)的依赖.但是对于scope是test,那不会进行依赖的传递.
有的时候为了避免这种间接的依赖,我们可以使用来排除依赖.
-
如果直接与间接依赖中包含有同一个坐标不同版本的资源依赖,以直接依赖的版本为准(就近原则)
-
如果直接依赖中包含有同一个坐标不同版本的资源依赖,以配置顺序下方的版本为准(就近原则
3.5 依赖归类
通常在项目中,我们会同时依赖同一个构件的不同模块,如 spring-orm-3.2.0,spring-context-3.2.0,且多个模块版本相同,为了维护和升级方便,我们可以对其同一管理,这时可以使用到 Maven 属性,类似于变量的概念。
<properties>
<springframework.version>3.2.0.RELEASE</springframework.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${springframework.version}</version>
</dependency>
</dependencies>