1、坐标
1.1 坐标有什么用
maven的一项重要工作就是管理依赖,那么现在就有一个问题,如何区别依赖?答案就是,坐标
##1.2 坐标详解
坐标包含以下元素:
groupId、artifactId、version、packaging、classfier
groupId
groupId定义了当前maven项目隶属的实际项目。这里的“实际项目”可以理解为一个包含很多maven项目的综合体,例如SpringFrameWork包含了spring-core、spring-context等很多模块。groupId的命名规则与java包名的表示方式类似,通常与域名的反向一一对应。例如groupId,org.sonatype.nexus,org.sonatype表示Sonatype公司建立的一个非盈利组织,nexus表示Nexus这一实际项目。
artifactId
artifactId定义了实际项目中的一个maven项目(模块)。命名推荐以“实际项目名-maven项目名”(例:nexus-indexer)的方式命名,这样的命名方式可以方便寻找实际构件:默认情况下,maven使用artifactId作为maven生成构件名,如nexus-indexer-2.0.0.jar,如果使用artifactId使用core这种命名的话,很多core-2.0.0.jar这样的文件,这样很难区分。
version
version定义了maven项目当前所处的版本。
packaging
packing定义了maven项目的打包方式。可以配置maven项目打包成jar或者war,不同的打包方式会影响到构建的生命周期,当没有定义packing的时候,maven默认使用jar。
classifier
classifier用来定义构建输出的一些附属构建。不能直接定义,需要附加的插件帮助生成。
上述5个元素中,groupId、artifactId、version必须定义,packing不定义默认为jar,classifier不能直接定义
2、依赖配置
一份完整的依赖配置
<dependency>
<groupId></groupId>
<artifactId></artifactId>
<version></version>
<type></type>
<optional></optional>
<scope></scope>
<classifier></classifier>
<systemPath></systemPath>
<exclusions>
<exclusion><exclusion/>
</exclusions>
</dependency>
groupId、artifactId、version
不多说,依赖的基本坐标
type
依赖的类型,对于坐标的packing元素,默认值为jar
scope
用来配置依赖的使用范围。maven在编译主代码、测试、运行时,使用不同的classpath,scope就是用来控制依赖与这三种classpath的关系
-
compile
编译依赖范围。如果没有指定scope,则默认为compile,使用compile,在三种classpath下都可以找得到依赖。
典型例子:spring-core,无论是编译、测试还是运行时都需要使用此依赖 -
test
测试依赖范围。只对于测试classpath有效。
典型例子:JUNIT,它只在编译测试代码和运行测试的时候才需要 -
provided
已提供依赖范围。该范围对主代码编译和测试classpath有效,但在运行时无效。换句话说,它只影响到编译,测试阶段。在编译测试阶段,我们需要这个artifact对应的jar包在classpath中,而在运行阶段,假定目标的容器已经提供了这个jar包,所以无需我们这个artifact对应的jar包了。
典型例子:servlet-api,编译和测试项目的时候需要该依赖,但在运行项目的时候,由于容器已经提供,就不需要重复引入了 -
runtime
运行时依赖范围。对于测试和运行classpath有效,但在编译主代码时无 效。
runntime表示被依赖项目无需参与项目的编译,不过后期的测试和运行周期需要其参与。
与compile相比,跳过编译而已,说实话在终端的项目(非开源,企业内部系统)中,和compile区别不是很大。比较常见的如JSR×××的实现,对应的API jar是compile的,具体实现是runtime的,compile只需要知道接口就足够了。oracle jdbc驱动架包就是一个很好的例子,一般scope为runntime。另外runntime的依赖通常和optional搭配使用,optional为true。我可以用A实现,也可以用B实现。 -
system 系统依赖范围。用于引入本地的,maven管理范围之外的依赖。
-
import
导入依赖范围。可以用来解决 maven 无法多继承的问题
optional
标记依赖是否可选
可选依赖:项目A依赖于项目B,项目B依赖项目X、Y,B对于X、Y的依赖都是可选依赖,这时,由于X、Y是可选依赖,X、Y将不会对A有任何影响。
场景:项目B实现了两个特性,特性一依赖于X,特性二依赖于Y,且两个特性互斥,用户不能同时使用这两个特性。那么需要在项目B的pom中声明X、Y的依赖的optional为true。这时候,如果A依赖了B,需要使用B的特性一,那么项目A中需要显示的声明X这一依赖,或者显式声明Y依赖,使用B的特性二。
简而言之,如果项目B的某个依赖d的optional为true,那么项目A引用项目B的时候,依赖d不会被A使用,需要A在自己的pom中进行显式引用。
exclusions
用来排除传递性依赖
传递性依赖:假设A依赖于B,B依赖于C,那么我们说A对于B是第一直接依赖,B对于C是第二直接依赖,A对于C是传递性依赖。
使用场景:A依赖于B,B依赖于C,但是C的版本过旧。此时可以使用exclusions排除该传递性依赖,并在A项目中显示声明一个最新版本的C依赖。
Optional与exclusions的区别
Optional定义后,该依赖只能在本项目中传递,不会传递到引用该项目的父项目中,父项目需要主动引用该依赖才行。
Exclusions则是主动排除子项目传递过来的依赖。