Maven学习(二) -- 坐标和依赖
标签(空格分隔): 学习笔记
坐标
实际就像在几何中,我们用一对坐标(x, y)来表示坐标系中唯一的点;或者我们可以用(经度,纬度)来表示地球上的某一个位置,在Maven的世界中,有坐标来唯一的表示项目。
他们由groupId
, artifactId
, version
, packaging
, classifier
等信息唯一的标识。
依赖
Maven会根据在POM中妹纸的信息自动下载所需要的依赖构件。
依赖的配置
<project>
<dependencies>
<dependency>
<groupId>...</groupId>
<artifactId>...</artifactId>
<version>...</version>
<type>...</type>
<scope>...</scope>
<optional>...</optional>
<exclusions>
<exclusion>
...
</exclusion>
...
</exclusions>
</dependency>
...
</dependencies>
...
</project>
其中,上述依赖元素的意义:
groupId
,artifactId
,version
:依赖的基本坐标,对于任何一个依赖来说,基本坐标是最重要的,Maven根据坐标才能找到需要的依赖;type
: 依赖的类型,对应于项目坐标蒂尼的packaging,大部分情况下为jar;scope
: 依赖的范围。optional
: 标记依赖是否可选;exclusions
: 用来排除传递性依赖。
依赖范围
这里的依赖范围主要针对上面scope
而言。
Maven在编译项目主代码的时候需要使用一套classpath,其中,编译,测试,运行使用不同的classpath。
依赖范围就是用来控制依赖于这三种classpath(编译classpath,测试classpath,运行classpath)的关系的。。。
- compile: 编译依赖范围。如果没有指定,则默认使用该依赖范围。使用此依赖范围的Maven依赖,对于编译,运行,测试三种classpath都有效。典型的例子是spring-core.
- test: 测试依赖范围。典型的例子是JUnit.
- provided: 已提供依赖范围。对于编译和测试classpath有效,而对运行classpath无效。典型的例子是servlet-api,编译和测试项目的时候需要该依赖,但在运行项目的时候,由于容器已经提供,就不需要Maven重复的引入了。
- runtime: 运行时依赖范围。对于测试和运行都有效。典型的例子是JDBC。在项目编译的时候只需要JDK提供JDBC接口,只有在运行或测试的时候才需要实现上述接口的具体JDBC驱动。
- system: 系统依赖范围。编译和测试时有效,应是无效。但使用system范围的依赖时必须通过systemPath元素显示地指定依赖文件的路径。由于此类依赖不是通过Maven仓库解析的,而且往往与本机系统绑定,可能造成构建的不可移植,因此应谨慎使用。
- import: 导入依赖范围。
传递性依赖
一个机遇Spring Framework的项目,如果不使用Maven,则在项目中就需要手动下载相关依赖:
做法一:下载一个很大的如spring-framework-2.5.6-with-dependencies.zip
的包,这里包含了所有Spring Frame的jar包,以及依赖的所有其他jar包,但这样往往会导致引入了很多不必要的依赖;
做法二:只下载spring-framework-2.5.6.zip
的包,到实际应用的时候根据其出错信息,再依次下载其他的包。
上面两种做法实际都是很繁琐的,在Maven中可以使用依赖性传递来解决这个问题。Maven会解析各个直接依赖的POM。将那些必要的间接依赖,以传递性依赖的形式引入到当前的项目中。
排除传递性依赖
例如如下场景:
- 场景一:当前项目中有一个第三方依赖,而这个第三方依赖由于某些原因依赖了另外一个类库的SNAPSHOT版本(该类库就成了项目的传递依赖),而SNAPSHOT可能是不稳定的,则必然会影响到该项目的稳定性,因此希望能够将这个传递依赖切除。
- 场景二:希望能够替换某个传递性依赖。例如一个项目A依赖一个类库X,而由于版本的原因,这个类库并不在中央仓库中。但是某个公司有个类似的实现包Y。所以我们想做的是将X的依赖切除,然后声明对Y的依赖。
排除传递性依赖实例:
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>com.park.mvnDemo</groupId>
<artifactId>project-a</artifactId>
<version>1.0.0</version>
<dependencies>
<dependency>
<groupId>com.park.mvn</groupId>
<artifactId>project-b</artifactId>
<version>1.0.0</version>
<exclusions>
<exclusion>
<groupId>com.park.mvnDemo</groupId>
<artifactId>project-c</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.park.mvnDemo</groupId>
<artifactId>project-c</artifactId>
<version>1.0.0</version>
</dependency>
</dependencies>
</project>
需要注意的是:声明exclusions的时候只需要groupId和artifactId,而不需要version,就可以唯一的定位依赖图中的某个依赖。(Maven解析后,不可能出现groupId和artifactId相同,但version不同的两个依赖。)
依赖调解
- 第一原则:路径最近者优先;
- 第二原则:第一声明优先。
- 在依赖路径长度相等的前提下,在POM中依赖声明的顺序决定了谁会被解析使用,顺序最靠前的那个依赖优胜。
在理想情况下,是不应该使用可选依赖的。使用的原因是:某一个项目实现了多个特性,而且这些特性间是互斥的。
可选依赖不被传递
假设有这样一个依赖关系:
项目A依赖于项目B,项目B依赖于项目X和Y,而且B对X和Y的依赖都是可选依赖:A->B, B->X(可选), B->Y(可选)。此时,X,Y将不会对A有任何影响,即可选传递不会传递下去。
可选依赖的配置:
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>com.juven.mvnDemo</groupId>
<artifactId>project-b</artifactId>
<version>1.0.0</version>
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.10</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>8.4-701.jdbc3</version>
<optional>true</optional>
</dependency>
</dependencies>
</project>
归类依赖
类似与Java中的常量定义,Maven中的依赖也应该在一个唯一的地方定义版本,并且在dependency声明中引用这一版本。这样,在升级一些包的时候只需要修改一处。
实例:
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>com.park.mvnDemo.account</groupId>
<artifactId>account-email</artifactId>
<name>Account Email</name>
<version>1.0.0</version>
<properties>
<springframework.version>2.5.6</springframework.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</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-context</artifactId>
<version>${springframework.version}</version>
</dependency>
</dependencies>
</project>
这里,使用<properties> <springframework.version>2.5.6</springframework.version> </properties>
定义一个Maven属性,然后后面使用${springframework.version}
来使用这个属性。
优化依赖
Maven会自动解析所有项目的直接依赖和传递性依赖,并且根据规则正确判断每个依赖的范围,对于一些依赖冲突,也能进行调节,以确保任何一个构件只有唯一的版本在依赖中存在。-- 得到的依赖成为已解析依赖(Resolved Dependency)。
- 查看项目中的已解析依赖:
- 使用命令
mvn dependency:list
; - 查看当前项目中的依赖树:
- 使用命令
mvn dependency:tree
; - 分析当前项目中的依赖:
- 使用命令
mvn dependency:analyze
.
如上便是Maven中依赖的主要内容。
Maven学习(二) -- 坐标和依赖的更多相关文章
- Maven学习笔记—坐标和依赖
Maven的坐标和依赖 1 Maven坐标 1.1 什么是Maven坐标 Maven坐标:世界上任何一组构件都可以使用Maven坐标来唯一标识,Maven坐标的元素包括groupId.artifact ...
- maven学习(九)——maven中的坐标、依赖以及仓库
一.Maven坐标 1.1.什么是坐标? 在平面几何中坐标(x,y)可以标识平面中唯一的一点. 1.2.Maven坐标主要组成 groupId:组织标识(包名) artifactId:项目名称 ver ...
- maven学习二(dependencies)
在前面一篇文章maven学习一(HelloWorld工程)已经对maven有了基本介绍,本文开始介绍maven依赖,通过如何如何增加log4j来学习maven的dependencies no-depe ...
- maven入门-- part4 坐标和依赖
Maven的坐标为各种构件引入了秩序,任何一个构件都必须明确的定义自己的坐标,maven的坐标包括如下的元素: groupId: 定义当前Maven项目隶属的实际项目 artifactId: 该元素定 ...
- Maven学习 二 Maven环境搭建
第一步:下载Maven并解压 注意选择镜像地址,选择国内的会快点 解压目录 Maven目录分析 bin:含有mvn运行的脚本 boot:含有plexus-classworlds类加载器框架 conf: ...
- Maven学习(二)-----Maven启用代理访问
Maven启用代理访问 如果你的公司正在建立一个防火墙,并使用HTTP代理服务器来阻止用户直接连接到互联网.如果您使用代理,Maven将无法下载任何依赖. 为了使它工作,你必须声明在 Maven 的配 ...
- Maven学习篇一:依赖了解
1.依赖配置 <project> ... <dependencies> <dependency> <groupId>xx</groupId> ...
- maven学习(六)依赖、聚合、继承
先说一下概念(个人理解的,有问题请留言): 依赖:我要盖一座房子,就需要很多的砖,这些专就是盖房子的一个依赖.我要跑一个maven项目,需要各种各样的功能,功能实现的jar包和插件就是我的依赖. 聚合 ...
- Maven专题1——坐标与依赖
1. 坐标 坐标用来唯一定位一个Maven构件: GAV(必需):groupId, artifactId, version packaging(可选): 可取值如:jar(缺省), war, pom, ...
- Maven学习 (二) Eclipse 上安装 Maven3插件
eclipse 安装插件的方式最常见的有两种: 1. 一种是在线安装,这貌似是用的最多的,就是:Help --> Install New Software,然后输入 HTTP 地址来安装,但 ...
随机推荐
- 对struct和class使用大括号初始化的测试
#include <iostream> using namespace std; struct struct1{ /* struct1(){ cout<<"this ...
- BizTalk开发系列(三十六) Orchestration单实例执行
BizTalk 是高效的消息处理引擎,采用多线程并发的方式来处理消息.也就是说当有消息被接收的时候就会产生一个新的消息处理实例.但有时目标系统可能并没有并发处理 的能力, 这时就需要在BizTalk中 ...
- JTA和JDBC事务
一般情况下,J2EE应用服务器支持JDBC事务.JTA事务.容器管理事务.这里讨论JTA和JDBC事务的区别.这2个是常用的DAO模式事务界定方式.JDBC 事务 JDBC 事务是用 Connecti ...
- java环境搭建系列:JDK从下载安装到简单使用
最近,问的比较多的问题居然是jdk的问题,对于新手来说这确实有点难度,毕竟一个人经常上网浏览新闻和观看视频的人,一下子开始一门编程语言的环境搭建.这中间需要一个慢慢适应的过程.回想当初我在这个阶段也很 ...
- php的字符串处理函数
Strpos($str,”img”); //返回字符串的位置 Substr($str,int start,int length); 使用这两个函数可以截取字符串
- Error:Unsupported major.minor version 51.0 .
替换了项目jar文件Tomcat运行报错, 项目开发环境jdk1.6,替换jar文件编译环境是1.7 修改eclipse java ->compiler和Installed JREs 重新编译替 ...
- C++和C代码互相调用是不可避免的
C++ 编译器能够兼容C语言发编译方式 C++编译器会优先使用C++ 编译的方式 extern 关键字能强制让C++编译器进行C方式的编译 external “C” { //do C-style co ...
- larave5.1l队列
官方文档http://laravel.com/docs/5.1/queues#dealing-with-failed-jobs 1.队列容器设置为数据库 config/queue.php 'defau ...
- [转]SQLSERVER如何获取一个数据库中的所有表的名称、一个表中所有字段的名称
1.查询数据库中的所有数据库名: SELECT Name FROM Master..SysDatabases ORDER BY Name 2.查询某个数据库中所有的表名: SELECT Name FR ...
- 前台 JSON对象转换成字符串 相互转换 的几种方式
在最近的工作中,使用到JSON进行数据的传递,特别是从前端传递到后台,前台可以直接采用ajax的data函数,按json格式传递,后台Request即可,但有的时候,需要传递多个参数,后台使用requ ...