【Maven】---坐标与依赖
Maven坐标与依赖
最近想深度学习下maven,找到一本书叫《Maven实战》,这本书讲的确实很好,唯一遗憾的是当时maven教学版本是3.0.0的,而目前已经到了3.5.4了,版本存在差距,
没关系,如果有时间和精力我也会阅读官方文档,看看到底有哪些变换。
一、坐标详解
1、何为Maven坐标
maven定义了这样一组规则:世界上任何一个构件都可以使用maven坐标唯一标识,坐标元素包括:groupId、artifactId、version、packaging、classifier。只要提供正确
的坐标就能从仓库中找到相应的构件供我们使用。maven从哪里下载构件呢?答:maven内置了一个中央仓库的地址,该中央仓库包含了世界上大部分流行的开源构件。
2、坐标详解
任何构件都必须明确定义自己的坐标,而一组maven坐标是通过一些元素定义的,他们是:groupId、artifactId、version、packaging、classifier。先看一组坐标定义如下
<groupId>org.sonatype.nexus</groupId>
<artifactId>nexus-indexer</artifactId>
<version>2.0.0</version>
<packaging>jar</packaging>
这是nexus-indexer项目的坐标,nexus-indexer是一个对maven仓库编纂索引并提供搜索功能的类库,它是Nexus项目的一个子模块。
goupId: 定义了当前maven项目隶属的实际项目,一般是域名+项目名。比如:com.alibaba.taotao
artifactId:该元素定义实际项目中的一个maven项目(模块,一般推荐项目名+子模块名。比如:taobao-web
version: 定义maven项目当前所处版本。
packaging:定义maven项目的打包方式,默认使用jar。
classifier:该元素用来帮助定义构件输出的一些附属构件。
上述5元素groupId、artifactId、version是必须的,packaging可选,默认jar,classifier不能直接定义。同时,项目构件的文件名是与坐标对应的,
一般的规则为artificatId-version[-classifier].packaging。packing并非一定与构件扩展名对应,比如packing为maven-plugin的构件扩展名为jar。
二、依赖详解
1、依赖的配置
一般的依赖只有基本的 groupId,artifactId,version。我们来看下详细的依赖配置
<project>
<dependencies>
...
<dependency>
<groupId>...</groupId>
<artifactId>...</artifactId>
<version>...</version>
<type>...</type>
<scope>...</scope>
<optional>...</optional>
<exclusions>
<exclusion>
...
</exclusion>
</exclusions>
</dependency>
...
</dependencies>
</project>
gourpId、artifactId、version:依赖的基本坐标,对于任何一个依赖来说,基本坐标是最重要的,maven根据坐标才能找到需要的依赖。
type:依赖的类型,对于项目坐标定义的packing,大部分情况是不必声明,默认是jar。
scope :依赖的范围 下面具体讲解
optional: 标记依赖是否可选,值为true或false,默认为false, 如果为可选依赖,则依赖不具有传递性。即B->X(可选依赖),A->B。此时A的依赖中不包含X。
exclusions:用来排除传递性依赖。
大部分依赖声明只包含基本坐标,然而在一些特殊情况下,其他元素至关重要。
2、依赖范围scope
classpath:用于指定.class文件存放的位置,类加载器会从该路径中加载所需的.class文件到内存中。maven在编译、执行测试、实际运行有着三套不同的classpath。
编译classpath:编译主代码有效
测试classpath:编译、运行测试代码有效
运行classpath:项目运行时有效
maven的依赖范围
compile:编译依赖范围。(默认方式),有效范围:编译classpath+测试classpath+运行classpath。
test:测试依赖范围。有效范围:测试classpath 比如:JUnit,只在测试时使用,在编译主代码和运行时不需要此依赖。
provided:已提供依赖范围。有效范围:编译classpath+测试classpath。
runtime:运行时依赖范围。有效范围:测试classpath+运行classpath。比如:JDBC驱动实现(mysql-connector-java)。
system:系统依赖范围。有效范围:编译classpath+测试classpath。使用system范围的依赖时必须通过systemPath元素显示地指定依赖文件的路径,
因为此类依赖不是通过maven仓库解析的,而且往往与本地及其系统绑定,可能造成构建的不可移植,慎用。systemPath元素可以引用环境变量。

<!--你引用本地的jar包,当然只能本地使用了-->
<dependency>
<groupId>javax.sql</groupId>
<artifactId>jdbc-stdext</artifactId>
<version>2.0</version>
<scope>system</scope>
<systemPath>${JAVA_HOME}/lib/rt.jar</systemPath>
</dependency> <!--你会发现这里这里是test,那么里面有个@Test 注解 只能在test目录下有效,在main目录下该注解是无效的-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
3、传递依赖性
假设A依赖B,B依赖C,则A对于B是第一直接依赖,B对于C是第二直接依赖,A对于C是传递性依赖。第一直接依赖的范围和第二直接依赖的范围决定了传递性依赖的范围。
如下表,最左边是第一直接依赖范围,上面是第二直接依赖范围,中间交叉单元格表示传递性依赖范围。

规律:
第二直接依赖范围是compile时,传递依赖的范围与第一直接依赖范围一致。
第二直接依赖范围是test时,依赖不会传递。
第二直接依赖范围是provided时,只传递第一直接依赖为provided的依赖。
第二直接依赖范围是runtime时,传递依赖的范围与第一直接依赖范围一致,但是compile例外,此时传递依赖范围为runtime。
4、依赖调节
Maven引入的传递性依赖机制,一方面大大简化和方便了依赖声明,另一方面,大部 分情况下我们只需要关心项0的直接依赖是什么,而不用考虑这些直接依赖会引人什么传 递性依赖。
但有时候,当传递性依赖造成问题的时候,我们就需要清楚地知道该传递性依 赖是从哪条依赖路径引入的。
例如,项目A有这样的依赖关系:A->B->C->X(1.0)、A->D->X(2.0),X是A的 传递性依赖,但是两条依赖路径上有两个版本的X,那么哪个X会被Maven解析使用呢?
两个版本都被解析显然是不对的,因为那会造成依赖重复,因此必须选择一个。Maven依 赖调解(Dependency Mediation)的第一原则是:
路径最近者优先。该例中X( 1.0)的路径氏 度为3,而X(2.0)的路径长度为2,因此X(2.0)会被解折使用。
依赖调解第一原则不能解决所有问题,比如这样的依赖关系:A->B->Y(1.0)、A-> C->Y(2.0),Y(1.0)和Y(2.0)的依赖路径长度是一样的,都为2。Maven定义了依赖调解的第二原则:
第一声明者优先。在依 赖路径长度相等的前提下,在POM中依赖声明的顺序决定了谁会被解析使用,顺序最前的那个依赖优胜。该例中,如果B的依赖声明在C之前,那么Y (1.0)就会被解析使用.
5、排除依赖
传递性依赖会给项目引入很多依赖,简化项目依赖管理,但是也会带来问题。
需求:比如当前项目有一个第三方依赖,而第三方依赖依赖了另一个类库的SNAPSHOT版本,那么这个SNAPSHOT就会成为当前项目的传递性依赖,而SNAPSHOT的不稳定性会直接影响到当前项目。
这时候就应该排除掉SNAPSHOT。并且声明该类库的正式发布版本。
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>3.6.10.Final</version>
<exclusions>
<exclusion>
<groupId>slf4j-api</groupId>
<artifactId>slf4j-api</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.12</version>
</dependency>
上述代码中hibernate-validator依赖slf4j-api,但是当前项目不想使用传递过来的slf4j-api,所以通过exclusions声明排除依赖。当前项目声明了自己需要的1.7.12版本的slf4j-api。
exclusions可以包含一个或者多fexdWon子元素,因此可以排除一个或者多 个传递性依赖。需要注意的是,声明exclusion的时候只需要groupld和artifactld,而不 笛要version元素,
这是因为只需要gmupkl和arlifactid就能唯一定位依赖图中的某个依 赖。换句话说,Maven解析后的依赖中,不可能出现groupW和artifactld相同,但是 version不同的两个依赖。
注意:排除依赖的时候也要注意,比如A依赖1.1版本的B, ,而你不想要1.1版本的B,而是要2.1的B,这个时候也需要考虑A跟2.1的B是否能兼容。

6、归类依赖
需求:关于springframework的依赖有好多,org.springframework:spirng-core:2.5.6、org.springframework:sprng-beans:2.5.6、org.springframework:spring-context:2.5.6,
他们来自同一个项目不同模块,因此版本都是相同的,可以预见在升级spring时这些依赖都会一起升级,为了方便统一所以使用properties元素定义maven属性。
<project>
....
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<springframework.version>4.3.2.RELEASE</springframework.version>
</properties> <!--通过使用${springframework.version}替换掉实际值,将所有spring依赖的版本值都使用这一引用值表示。-->
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${springframework.version}</version>
</dependency>
</dependencies>
...
</project>
参考
《Maven实战》. 许晓斌
同时很高兴,找到看过这本书的人的总结。
坐标详解:https://www.jianshu.com/p/30ece967dccd
依赖配置:https://www.jianshu.com/p/79cf4423281a
我只是偶尔安静下来,对过去的种种思忖一番。那些曾经的旧时光里即便有过天真愚钝,也不值得谴责。毕竟,往后的日子,还很长。不断鼓励自己,
天一亮,又是崭新的起点,又是未知的征程(上校20)
【Maven】---坐标与依赖的更多相关文章
- 03 Maven 坐标与依赖
Maven 坐标与依赖 Maven 的一大功能是管理项目依赖.为了能自动化地解析任何一个 Java 构件, Maven 就必须将它们唯一标识,这就依赖管理的底层基础 一一 坐标.本章将详细分析 Mav ...
- 4.Maven概念模型,maven的生命周期,Maven坐标,依赖管理(依赖范围,依赖声明),仓库管理,私服概念
1 maven概念模型 2 maven的生命周期,项目构建过程 watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdG90b3R1enVvcXVhbg== ...
- 3.Maven坐标和依赖
1.1 何为Maven坐标 正如之前所说的,Maven的一大功能就是管理项目依赖.为了能自动化地解析任何一个Java构件,Maven就必须将它们唯一标识,这就依赖管理的底层基础——坐标. 1.2 坐标 ...
- maven坐标及依赖范围的学习(1)
首先,我们先了解什么是maven的坐标(重中之重): 在这里我们可以看到那三个红色的行,基本是pom.xml中出现的最多的配置 例如这个配置:这里我们可以看到我们这个项目的pom文件中,他对名 ...
- Maven学习笔记—坐标和依赖
Maven的坐标和依赖 1 Maven坐标 1.1 什么是Maven坐标 Maven坐标:世界上任何一组构件都可以使用Maven坐标来唯一标识,Maven坐标的元素包括groupId.artifact ...
- Maven学习(二) -- 坐标和依赖
标签(空格分隔): 学习笔记 坐标 实际就像在几何中,我们用一对坐标(x, y)来表示坐标系中唯一的点:或者我们可以用(经度,纬度)来表示地球上的某一个位置,在Maven的世界中,有坐标来唯一的表示项 ...
- Maven之——坐标和依赖(上)
Maven之--坐标和依赖(上) 1. Maven坐标概念 Maven通过构件的坐标来在Maven仓库中定位到详细的构件.Maven的坐标元素包含groupId.artifactId.versi ...
- Maven学习笔记2(坐标和依赖)
1.坐标 Maven坐标为各个构件建立了秩序,任何一个构件都必须明确自己的坐标,一个maven坐标是由一些元素确定的 <groupId>com.alivn.account</grou ...
- 《Maven实战》第5章 坐标和依赖
5.1 Maven坐标——项目唯一标识 groupId(必须定义):定义Mavan项目隶属的实际项目,如SpringFramework,一个实际项目可包含多个Maven项目 artifactId(必须 ...
随机推荐
- 原生js触碰到底部触发函数;
/** function __morebook(){ console.log(123) } ScrollBottom(function(){__morebook();}); **/ //如果直接写一个 ...
- Oracle表导入Mysql方法
public void reportPerInfo(){ //每次导入清除之前数据 this.esEntPermitErrDao.updateObjectBySql("delete from ...
- 【java】-- 线程安全
1.线程安全问题介绍与案例分析 当多个线程同时共享,同一个全局变量或静态变量,做写的操作时,可能会发生数据冲突问题,也就是线程安全问题.但是做读操作是不会发生数据冲突问题. 案例:需求现在有100张火 ...
- C# 中传参中的OUT 和 ref 区别 笔记
//out传参前需要对参数进行赋值处理,ref则不需要.//out.ref 传参都可以对值进行改变 1 static void Main(string[] args) { ; //int J = 10 ...
- 最简单的原生js和jquery插件封装
最近在开发过程中用别人的插件有问题,所以研究了一下,怎么封装自己的插件. 如果是制作jquery插件的话.就将下面的extend方法换成 $.extend 方法,其他都一样. 总结一下实现原理: 将 ...
- hive求TopN语句
ROW_NUMBER,RANK(),DENSE_RANK() 先了解这三个之间的区别: Rank():1,2,2,4,5(一般用这个较多,不会影响总排名) Dense_rank():1,2,2,3,4 ...
- Python使用ProtoBuffer
Python使用ProtoBuffer Protocol Buffers,是Google公司开发的一种数据描述语言,类似于XML能够将结构化数据序列化,可用于数据存储.通信协议等方面. 就可读性而言感 ...
- 三、糖醋鲤鱼(Sweet and sour carp)
糖醋鲤鱼是用鲤鱼制作的一道山东济南传统名菜,为鲁菜的代表菜品之一 ,色泽金黄,外焦内嫩,酸甜可口,香鲜味美. 菜品历史 <诗经>载:岂食其鱼,必河之鲤.<济南府志>上早有&qu ...
- iptables实现--kafka限制ip地址访问
iptables -I INPUT -p tcp --dport 9092:9094 -j DROPiptables -I INPUT -s 10.144.137.32 -p tcp --dport ...
- ora-01033 oracle initialization or
这次出现这个问题是源于错删了 DBF文件. 解决方案如下: 1.打开SQL Plus 最后把你删掉的那个文件的表空间删掉就好了