maven依赖配置和依赖范围
一:依赖配置
我们在实际开发汇中最常见的maven依赖如下,读者可以看到最基本的groupId,artifactId,version等元素组成。
1 <dependency>
2 <groupId>...</groupId>
3 <artifactId>...</artifactId>
4 <version>..</version>
5 <type>...</type>
6 <scope>...<scope>
7 <optional>...<optional>
8 <exclusions>
9 <exclusion>
10 </exclusion>
11 </exclusions>
12 <dependency>
1.groupId、artifactId和version:依赖的基本坐标,对于任何一个依赖来说,基本坐标最重要,Maven根据坐标才能找到需要的依赖。
2.type依赖类型,对于项目坐标定义的packaging。大部分情况下,该元素不必要声明,其默认值为jar。
3.scope 依赖范围。我们会在后面详细介绍。
4.optional:标记依赖是否可选。
5.exclusions:用来排除传递性依赖。
在实际应用中只包含最基本的坐标,然而在一些特殊情况下,其他元素至关重要。
二.依赖范围
依赖范围就是用来控制依赖与这三种classpath(编译classpath、测试classpath、运行classpath)的关系,Maven有以下几种依赖范围。
1.compile: 编译依赖范围。如果没有指定,就会默认使用该依赖范围。使用此依赖范围的maven依赖,对于编译 测试 运行三种的classpath都有效。
2.test:测试依赖范围。使用此依赖范围的Maven依赖,只对于测试的classpath有效,在编译主代码或者运行主代码的时候都无法依赖此类依赖。典型的例子是jUnit,它只有在编译测试代码及运行测试代码的时候才有效。
3.provided:以提供依赖范围。使用此依赖范围的maven依赖,对于编译和测试classpath有效,但在运行时无效。典型的例子是servlet-api,编译和测试项目的时候需要该依赖,但在运行的时候,由于容器已经提供,就不需要maven重复地引入一遍。打包的时候可以不用包进去,别的设施会提供。事实上该依赖理论上可以参与编译,测试,运行等周期。相当于compile,但是打包阶段做了exclude操作
4.runtime:运行时依赖范围。使用此依赖范围的maven依赖,对于测试和运行classpath有效,但在编译主代码时无效。典型的例子是JDBC驱动实现,项目主代码的编译只需要jdk提供的jdbc的接口,只有在执行测试或者运行测试的时候才需要实现上述接口的jdbc的驱动
5.system:系统依赖范围。从参与度来说,和provided相同,不过被依赖项不会从maven仓库下载,而是从本地文件系统拿。需要添加systemPath的属性来定义路径,该依赖与三种范围的classpath
和provided依赖范围完全一致。可能造成不可移植,谨慎使用。
6.import:导入依赖范围。该依赖范围不会对三种classpath产生实际的影响。只有在dependencyManagement下才有效果。
3.传递性依赖
A依赖B,B依赖C。当前项目为A,只当B在A项目中的scope,那么c在A中的scope是如何得知呢?
当C是test或者provided时,C直接被丢弃,A不依赖C;(排除传递依赖)
否则A依赖C,C的scope继承与B的scope。maven会解析各个依赖的pom,将那些必要的间接依赖,一传递性依赖的形式引入到当前的项目中。
3.传递性依赖范围
假设A依赖于B,B依赖于C,我们说A对于B是第一直接依赖,B对于C第二直接依赖,A对于C的传递性依赖。
4.依赖调解
针对于传递性依赖造成问题的时候,我们需要清楚知道传递性依赖的从哪条路径引入的。例如A->B-C->X(1.0) A->D
->X(2.0),两条路径有两个版本的X,两个版本都被解析是不对的,因为会造成依赖重复,因此必须选择一个。maven依赖调解(Dependency Mediation)第一条原则是:路径最近者优先。因此X(2.0)会被解析使用。当路径相同时我们采取第二条准则,第一声明者优先。即谁在pom文件中先声明,先被解析。
5.排除依赖
exclusions 可以包含一个多个exclusion元素,可以排除一个或多个项目。声明exclusion时只需要groupId和artifactId和两个属性,因为这两个属性就可以定位一个项目
6.归类依赖
同一类型的依赖升级时每个都要写版本,可以使用常量来替代这些版本。例
<properties> <springframework.version>2.5.6</springframework.version> </properties> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>${springframework.version}</version> </dependency> </dependencies>
使用美元符号和花括号方式引用maven属性
7.远程仓库的配置
在很多情况下,默认的中央仓库是无法满足项目的需求,可能项目需要的构件存在于另一个远程仓库中,如JBoos Maven仓库
<repositories> <repository> <id>jboss</id> <name>JBoos Repository</name> <url>http://repository.jboos.com/maven2/</url> <releases> <enabled>true</enabled><!--开启JBoos仓库发布版本下载支持--> </releases> <snapshots> <enabled>false</enabled><!--关闭下载JBoos快照版构件--> <updatePolicy>daily</updatePolicy> <checksumPolicy>ignore</checksumPolicy> </snapshots> </repository> </repositories>
对于releases和snapshots标签,他们还有两个子元素updatePolicy和checksumPolicy 。元素updatePolicy是用来配置maven从远程仓库检查更新的频率,默认值是daily,表示maven每天检查一次,其他可用值包括:never--从不检查更新;always--每次构件都检查更行;interval:X--每隔X分钟检查一次更新(X为任意整数);checksumPolic不常用,用时在百度去。
8.远程仓库的认证
百度
9.部署至远程仓库
<distributionManagement> <!--发布版本构件仓库--> <repository> <id>proj-release</id> <name>Proj Release Repository</name> <url>..my url..</url> </repository> <!--快照版本构建仓库--> <snapshotRepository> <id>proj-release</id> <name>Proj Release Repository</name> <url>..my url..</url> </snapshotRepository> </distributionManagement>
配置完成后运行 mvn clean deploy 。 maven2会根据模块的版本号(pom文件中的version)中是否带有-SNAPSHOT来判断是快照版本还是正式版本。如果是快照版本,那么在mvn deploy时会自动发布到快照版本库中,会覆盖老的快照版本,而在使用快照版本的模块,在不更改版本号的情况下,直接编译打包时,maven会自动从镜像服务器上下载最新的快照版本。如果是正式发布版本,那么在mvn deploy时会自动发布到正式版本库中,而使用正式版本的模块,在不更改版本号的情况下,编译打包时如果本地已经存在该版本的模块则不会主动去镜像服务器上下载
10.仓库搜索服务
使用maven进行开发时,一个常见的问题就是如何寻找需要的依赖,我们可能知道需要使用类库的项目名称,但是添加maven依赖需要准确的坐标,下边介绍几个常用的公共maven仓库搜索服务。
01.Sonatype Nexus 地址http://repository.sonatype.org/
02.Mvnrepository 地址https://mvnrepository.com/
11.聚合
我们有时候会一次想构件多个项目,而不是到两个模块下分别执行mvn命令。maven聚合(也叫多模块)这一特性就是为这一需求服务的。我们需要建立一个额外的maven模块,然后通过该模块构件整个项目所有的模块,这个新的块不需要有src下所有目录,但是必须要有一个自己的pom文件。然后在聚合模块运行 mvn install 会发现所有的模块会一起打包,与原来单个打包无差别。下边为一个聚合模块的基本内容。
<groupId>com.stu.mvn</groupId> <artifactId>stuMvn-aggregator</artifactId> <version>1.0-SNAPSHOT</version> <!--打包类型必须为pom--> <packaging>pom</packaging> <name>stuMvn Aggregator</name> <modules> <!--为了打包方便通常将聚合模块放在最顶层,其他模块则作为聚合模块的子目录存在, 要是不是目录级别,这里的module就需要定位到子模块的相对路径, 本例是聚合模块和其他模块在同一级别需要../其他模块的artifactId--> <module>../stuMvn</module> </modules>
执行mvn install 会将所有的项目打包,但有些时候用户只想打包其中的一个或者多个,maven还提供了很多命令支持这些炒作(mvn -h 查看这些命令):
-am , 同时构建所列模块的依赖模块 mvn clean install -pl artifactId1 -am
-amd, 同事构建依赖于所列模块的模块 mvn clean install -pl artifactId -amd
-pl, 构件指定模块,模块间用逗号隔开 mvn clean install -pl artifactId1,artifactId2,...
-rf, 从指定的模块开始构件(指定模块的构件顺序,估计时最常用的一个)
这几个命令可以相互组合,在开发的过程中,灵活运用这四个参数,可以帮助我们跳过那些无需构件的模块,从而加速构建,在项目庞大,模块多的时候,这种效果会特别明显。
12.继承
<groupId>com.stu.parent</groupId> <artifactId>stu-parent</artifactId> <version>1.0-SNAPSHOT</version> <packaging>pom</packaging><!--打包类型必须为pom--> <name>stu-parent</name>
上面是是父模块pom中的基本内容了,使用和子模块相同的groupId和version,父模块只是为了让子模块继承,因此也是不需要pom文件之外的其他文件了。然后在需要继承的子模块中写入下列内容。
<parent> <groupId>com.stu.parent</groupId> <artifactId>stu-parent</artifactId> <version>1.0-SNAPSHOT</version> <!--通常子类总是能找到父类项目的地址,此处可省略--> <relativePath>../stuparent/pom.xml</relativePath> </parent>
maven可被继承的pom元素:
groupId :项目组 ID ,项目坐标的核心元素;
version :项目版本,项目坐标的核心元素;
description :项目的描述信息;
organization :项目的组织信息;
inceptionYear :项目的创始年份;
url :项目的 url 地址
develoers :项目的开发者信息;
contributors :项目的贡献者信息;
distributionManagerment :项目的部署信息;
issueManagement :缺陷跟踪系统信息;
ciManagement :项目的持续继承信息;
scm :项目的版本控制信息;
mailingListserv :项目的邮件列表信息;
properties :自定义的 Maven 属性;
dependencies :项目的依赖配置;
dependencyManagement :醒目的依赖管理配置;
repositories :项目的仓库配置;
build :包括项目的源码目录配置、输出目录配置、插件配置、插件管理配置等;
reporting :包括项目的报告输出目录配置、报告插件配置等。