在当前的编码工作中,几乎是百分之九十会使用 maven 了,但从来没系统地学习过,仅仅是照葫芦画瓢跟着使用,报错了也往往是去谷歌解决,所以为了更好地使用,系统学习 maven 是必要的。
maven 简单介绍
maven 主要服务于基于 java 平台的项目构建、依赖管理,和项目信息管理。
maven 的优点
- maven 是跨平台的,因此无论是在 windows 还是 mac 上,都可以使用相同的命令。
- 标准化构建过程,避免不必要的学习成本。
使用入门
pom 文件
maven 的 pom 文件定义了项目的一些基本信息,描述了项目如何构建,声明依赖。
一个简单的 pom 文件1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>top.zhyee</groupId>
<artifactId>hello-world</artifactId>
<version>2.0.0</version>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>org.java-websocket</groupId>
<artifactId>Java-WebSocket</artifactId>
<version>1.3.9</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>
坐标
pom 文件中最重要的是 groupId、artifactId、version,这三个元素组成了项目的坐标,可以说是项目在 maven 世界中的名片。
- groupId 定义了组的概念,实际工作中通常和公司关联,比如 io.daocloud.mircoservice
- artifactId 定义了项目在当前组中的唯一 id,比如 hello-world
- version 定义了项目当前版本,带有 SNAPSHOT 的表明项目处于开发阶段,还不稳定。
一般来说,项目中的包名都应该基于项目的 groupId 和 artifactId ,这样更加清晰。
打包方式
在上面的 pom 文件中,packaging 元素指定了项目的打包方式为 jar。其实这里不用显示指定,因为 maven 的默认打包方式为 jar。可以显示指定其他的打包方式,如 war。
依赖
dependencies 标签中声明了项目的依赖,maven 根据声明的坐标来找到依赖,scope 标签声明了依赖的范围,用来控制依赖与 classpaath 的关系。
maven 在编译项目主代码时需要一套 classpath,同时,在编译和测试时,又会使用另外的 classpath。因此,定义了依赖范围,就可以告诉 maven 是在什么情况下引入这个依赖。
依赖范围 | 编译 | 测试 | 运行 |
---|---|---|---|
compile | √ | √ | √ |
test | √ | ||
provided | √ | √ | |
runtime | √ | √ | |
system | √ | √ | |
import |
一些概念
传递性依赖
如果 A 依赖于 B , B 依赖于 C ,那么 maven 在解析 pom 时,会将 C 以传递性依赖的形式引入到 A。
依赖调解
假如有这样的依赖关系 A->B->C->D(1.0),A->F->D(2.0),那么最终引入的 D 会是哪个版本呢。
maven 依赖调解的第一原则是路径最近者优先,在这个例子中,2.0 版本更近,因此会被解析使用。
那么路径一样的情况下呢,如 A->C->D(1.0),A->F->D(2.0)
为了解决这个问题,maven 定义了依赖调解的第二原则,即第一声明者优先。在 pom 文件中定义的依赖顺序将决定哪一个版本的 jar 包会被解析使用。