🏭仓库 - 图1

仓库布局

仓库布局是指 一个库在仓库里的存储路径,而Maven是通过jar包的坐标来确定一个包的唯一存储路径。举个例子,现在有一个jar包的坐标:

  1. groupId: org.apache.kafka
  2. artifactId: kafka-clients
  3. version: 0.10.0.0

那么这个包在库中以如下方式存储:
<仓库根目录>/org/apache/kafka/kafka-clients/0.10.0.0/kafka-clients-0.10.0.0.jar

仓库分类

本地仓库

存储在本地的仓库。
每个用户在自己的用户目录下都有一个.m2/repository/的仓库目录

如果想自定义的话,就找到settings.xml里面修改<settings>元素中的<localRepository>元素,配置为想要的目录

远程仓库

如果本地仓库没有依赖,就会去远程仓库下载。

中央仓库

所有下载请求都默认从中央仓库里下载。

私服

公司自己假设的Maven仓库,通常放在局域网上供公司职员使用。

其他仓库

有些依赖可能在中央仓库没有,或者中央仓库的速度太慢,此时可能会用其他的一些远程仓库,比如jboss的仓库。java.netgooglecodehausjboss 等等,还有一些其他公司自己搞的Maven仓库,有少数的依赖包可能在中央仓库里找不到,只在其他仓库里。

各类仓库的层级关系

maven多层仓库架构.png

版本分类

正式版本

已经完全通过编译、测试、QA等等测试,是可以投入生产环境使用的版本。

快照版本

快照版本的存在主要是为了协同合作时,双方能更好合作而存在的。比如小张正在开发【模块A的2.1版本】,小李开发的【模块B】需要依赖【模块A】。现在有三种方案:

  1. 小李 主动去拉取 小张 的【模块A】并自己构建(麻烦,不推荐)
  2. 小张重复部署 【模块A的2.1版本】,但是小李第一次下载过后会在本地仓库缓存一份,即使小张一直更新 【模块A】,小李也没办法拉取【模块A的2.1版】,除非每次拉取都去本地仓库里删除。
  3. 小张每更新一次代码就更新版本号并部署【模块A的2.2】、【模块A的2.3】、【模块A的2.4】等等版本,小张和小李都需要不停修改pom.xml

如果使用快照版本——【模块A的2.1-SNAPSHOT】,每次小李构建项目时Maven都会重新去拉取【模块A的2.1-SNAPSHOT】版本。

每次发布快照版本时,快照版本的jar包会带上一个时间戳,这个时间戳不影响用户使用,仅仅是Maven用于衡量最新的快照版本的依据。

比如小李要构建项目时需要,Maven会去检查远程仓库的快照版本和本地仓库的快照版本是否一致,判断标准就是快照版本携带的时间戳。

从仓库解析依赖的机制流程

  1. 如果依赖范围是systemMaven直接从本地文件系统查找jar包
  2. 根据目标jar包的坐标计算仓库路径后,从本地仓库里寻找jar包
  3. 本地仓库不存在相应jar包时,若依赖的版本是 显示的发布的 版本,比如1.0.01.2.3-RELEASE等等,则遍历所有的远程仓库,发现后下载到本地仓库并解析使用。
  4. 若依赖的版本是 RELEASELATEST,则基于 更新策略 读取所有远程仓库的元数据(元数据的地址通常是/<groupId>/<artifactId>/maven-metadata.xml),随后将其与本地仓库的对应元数据合并比较后,就能计算出最新的RELEASELATEST真实的值,然后基于这个真实的值检查本地和远程仓库。
  5. 若依赖的版本是 SNAPSHOT,则基于更新策略读取所有远程仓库的元数据(此时元数据的地址通常是/<groupId>/<artifactId>/<version>/maven-metadata.xml),随后将其与本地仓库的对应元数据合并比较后,就能计算出最新快照版本的值,然后基于该值检查本地仓库 或者 从远程仓库下载。
  6. 如果最后解析得到jar包时间戳格式的快照,比如1.0.0-20210908.121423-1,则复制其时间戳格式的文件 为 一个非时间戳的格式,比如1.0.0-SNAPSHOT,然后使用非时间戳的文件。

镜像

这里的镜像就类似于副本的意思,阿里云就有一个Maven中心仓库的镜像,通过这个镜像,我们可以快速下载Maven中心仓库里的包。配置方式如下所示:

<!-- 在 <mirrors>元素中 添加如下的元素 -->
<mirror>
  <id>nexus</id>
  <mirrorOf>*</mirrorOf>
  <url>http://127.0.0.1:8082/repository/maven-public/</url>
</mirror>

提问

  • Q:本地仓库有SNAPSHOT有带时间戳和不带的包,请问依赖他的项目导入优先级是选择带时间戳还是不带时间戳的
  • A:本地仓库里的每个包下都有一个maven-metadata-local.xml文件,实际是比较这个文件里的<lastUpdated>来导入最新的

  • Q:什么情况下打的包会带时间戳,因为我单一项目install多次,都是不带时间戳的jar包,有点搞不懂

  • A:快照版本上传到私服上都会带有时间戳,本地install的不会带有。