Maven项目的核心是pom.xml。POM(Project Object Model,项目对象模型)定义了项目的基本信息,用于描述项目如何构建,声明项目依赖等。
pom文件结构.png
一、基本信息
- modelVersion:指定当前POM模型的版本,对Maven2和Maven3来说,他只能是4.0.0
- groupId:项目的所属公司或组织的域名倒写
- artifactId:如果该项目为一个Maven模块,则相当于项目名;如果一个项目包含多个子模块,则它们该模块的名称;(一般和项目同名)
- version:该项目的版本信息
- name:项目名,作用只是一个更友好的项目名称,不是必须的。
- packaging:打包方式,默认为jar
二、依赖管理
依赖管理xml结构.png
一般添加以来只需要groupId、artifactId、version三个标签
- groupId:如上groupId
- artifactId:如上artifactId
- version:如上version
- type:如上packaging,默认为jar
- scope:依赖的范围 之后详细说明
- optional:标记依赖是否可选 之后详细说明
- exclusions:用来排除一些传递性依赖 之后详细说明
2.1、依赖范围(scope)
- 首先Maven编译项目主代码时需要一套classpath
- 其次Maven在编译和执行测试的时候会使用另一套classpath
- 最后,在实际运行Maven项目的时候,又会使用一套classpath
依赖范围(scope)就是用来控制依赖以上三种classpath(编译classpath、测试classpath、运行classpath)的关系,具体如下:
- compile:编译依赖范围
- 如果没有指定、默认为该依赖范围
- 使用此范围,对于编译、测试、运行三种classpath都有效
- test:测试依赖范围
- 只对测试classpath有效
- 在编译主代码和运行项目使用时将无法使用此类依赖
- 如JUnit
- provided:编译及测试依赖范围
- 对于编译及测试classpath有效,但是在运行时无效
- 例如servlet-api,编译和测试项目时需要该依赖,但是在运行项目的时候,容器已经提供,所以不需要Maven重复引入一遍
- runtime:运行时依赖范围
- 对于测试和运行的classpath有效
- 例如JDBC的驱动实现,项目主代码的编译只需要JDK提供的JDBC接口,只有在执行测试或者运行项目的时候才需要具体JDBC的实现
- system:系统依赖范围
- 依赖范围和provided的范围完全一致
- 使用该范围需要使用systemPath元素显式的依赖文件的路径
-
往往和本机绑定,可能造成构建的不可移植
依赖范围与classpath的关系.png
2.2、传递性依赖(exclusions)
什么是传递性依赖?
例如一个项目依赖spring-core的jar包,然后spring-core依赖commons-logging,则commons-logging为该项目的一个传递性依赖
2.3 传递性依赖和依赖范围
依赖范围不仅可以控制依赖与三种classpath的关系,还对传递性依赖产生影响。
假设A依赖B,B依赖C,A对于B是第一直接依赖、B对于C是第二直接依赖、A对于C是传递性依赖
下边最左边一列为第一直接依赖、最上边是第二直接依赖,中间交叉单元格则表示传递性依赖范围
依赖范围影响依赖传递.png
2.4依赖调解
例如有项目A存在以下关系:A -> B -> C -> X(1.0)、A -> D -> X(2.0),X是A的传递性依赖,但是却有两个版本的X,Maven有两个原则去调解依赖重复。
- 路径最近者优先
- 第一声明者优先
最好的做法:可使用exclusions标签对一些传递性依赖进行排除
2.5.可选依赖(optional)
假如项目A依赖项目B,项目B依赖于项目X和Y,B对于X和Y都是可选依赖:A -> B、B -> X\Y(可选),X、Y不会得以传递,称为传递性依赖。
引入这种依赖特性的原因主要是,可能项目B实现了两个特性,一个特性依赖X,一个特性依赖Y,而且这两个特性是互斥的。
、构建管理
构建管理常见标签.png