type
status
date
slug
summary
tags
category
icon
password
在 Maven 的日常使用经常涉及这几个概念
  • 仓库(Repository)
  • 镜像(Mirror)
  • 私服(Nexus)
这些概念容易混淆,在这里详细记录一下。里面涉及到一些 Maven 的配置,可以参考后面的配置文章。

一、Maven 仓库

Maven 仓库(Repository),顾名思义是一个存储 JAR 文件的仓库,Maven 根据项目中 pom.xml 文件中提供的 jar 包依赖信息,从存储库中查找并获取需要的 jar 包。
Maven Repository有3种类型:
  • Local Repository:本地仓库
  • Central Repository:中央仓库
  • Remote Repository:远程仓库
Maven项目在搜索依赖的时候,根据以下顺序获取相关的依赖包。
本地仓库 > 中央仓库 > 远程仓库
项目所需要的所有构件都是先从本地仓库获取的,如果本地仓库没有,会尝试去中央仓库获取,如果中央仓库也没有,它会尝试从远程仓库下载构件到本地仓库,然后再使用本地仓库的构件。

本地仓库

不需要联网的本地磁盘目录。如果目录不存在,第一次执行 Maven 时就会先创建它。默认情况下,Maven 本地存储库的地址是 ${user.home}/.m2/repository/ 。可以通过修改 MAVEN_HOME/conf/settings.xml 文件来更改 Maven 本地存储库的位置。

中央仓库

需要联网的内置的远程仓库。由 MAVEN 社区提供和管理的仓库,包含了大量常用的类库,默认中央仓库:https://repo.maven.apache.org/maven2
中央仓库不需要在工程/代码中手动配置,是 MAVEN 缺省的远程仓库。Maven 默认有一个 super pom 文件。super pom 文件位置位于 MAVEN_HOME/lib 下的 maven-model-builder-3.5.4.jar 中的 org/apache/maven/model/pom-4.0.0.xml
这里设置了中央仓库的 id 为 central,远程 url 地址为 http://repo.maven.apache.org/maven2,并关闭了 SNAPSHOT 版本构件下载的支持
所以在 settings 文件配置一个 mirrormirrorOfcentral 的镜像就可以替代中央仓库了(镜像的概念下面再说)。

远程仓库

需要联网的、由开发人员自己定制的仓库。例如一个公司可能有很多共享的 jar 包文件,就可以搭建一个公司内部的远程库,供内部开发人员使用(中央库可以认为是一个特殊的远程库)。
可以在 pom.xml 中配置远程库,添加下面内容到 pom.xml 中就配置了一个远程库。
我们可以在 pom 文件单独配置 repository,但是随着项目越来也多我们每次都要在 pom 文件配置比较麻烦,所以我们可以在
setting.xml 文件配置 profile (私服)。这样我们每次创建新项目的时候就可以不用配置 repository

二、Maven 镜像

如果仓库 A 可以提供仓库 B 存储的所有内容,那么就可以认为 A 是 B 的一个镜像(mirror)。换句话说,任何一个可以从仓库获得的构件,都能从它的镜像中获取。
mirror 相当于一个拦截器,它会拦截 Maven 对 remote repository 的相关请求,把请求里的 remote repository 地址,重定向到 mirror 里配置的地址。下面的例子中,B Repository 被称为 A Repository 的镜像,在获取 jar 包将从 B Repository 获取,此时 A Repository 将失去作用。
notion image
mirror 的配置语法如下,mirrorOf 表示要替换的 repositoryid。例如我们要设置了一个 Maven 中央仓库 http://repo.maven.apache.org/maven2/ 的镜像,就需要将该元素设置成 central ,这必须和中央仓库的 id 完全一致
为什么配置镜像?
  1. 一句话,你有的我也有,你没有的我也有。(拥有远程仓库的所有 jar,包括远程仓库没有的 jar)
  1. 还是一句话,我跑的比你快。(有时候远程仓库获取 jar 的速度可能比镜像慢,这也是为什么我们一般要配置中央仓库的原因,外国的 maven 仓库一般获取速度比较慢)
如果你配置 maven 镜像不是为了以上两点,那基本就不用配置镜像了。

三、Maven 私服

私服是一种特殊的远程 Maven 仓库,它是架设在局域网内的仓库服务,私服一般被配置为互联网远程仓库的镜像,供局域网内的 Maven 用户使用。
当 Maven 需要下载构件的时候,先向私服请求,如果私服上不存在该构件,则从外部的远程仓库下载,同时缓存在私服之上,然后为 Maven 下载请求提供下载服务,另外,对于自定义或第三方的 jar 可以从本地上传到私服,供局域网内其他 Maven 用户使用。
私服的配置推荐用 profile 配置而不是 mirror。配置私服的语法如下:

四、仓库优先级

为了方便测试,我准备了以下几个仓库
  • 172.16.xxx.xxx 远程仓库 (私服)
  • dev.xxx.wiki 远程仓库 (远程)
  • localhost 仓库 是我自己在本机搭建的一个仓库 (镜像)
  • maven.aliyun.com 中央仓库(中央)

本地仓库优先级

Maven 本地仓库拥有该包,而远程、镜像、中央、私服都不包含该包。我们来看下 Maven 是怎么获取的
从上面可以看出 Maven 一开始就使用本地仓库,并将本地仓库的优先级定制为 10 , 最后 jar 包也在本地仓库找到,Maven 成功打包。

远程仓库优先级

前面我们知道了,本地仓库的优先级是最高的,现在我们继续研究远程仓库的优先级(以下的所有例子,都默认本地仓库不拥有我们需要的包)
这一次我们默认配置 profile(私服)为 172.16.xxx.xxx 远程仓库,repository 为 dev.xxx.wiki 远程仓库,mirror 为本地 localhost 仓库,还配置了一个 mirrorOf 为 central 远程仓库为 maven.aliyun.com 的中央仓库。配置信息如下:
settings.xml 文件
pom.xml 文件
以下是 Maven 拉取包的日志
好了,看了这么多的配置文件信息和日志信息,我们也总结一下 Maven 远程仓库优先级了。
  1. 从日志信息我们得出这几种 maven 仓库的优先级别为
本地仓库 > 私服 (profile)> 远程仓库(repository)和 镜像 (mirror) > 中央仓库 (central)
  1. 镜像是一个特殊的配置,其实镜像等同与远程仓库,没有匹配远程仓库的镜像就毫无作用(如 foo2)。
  1. 总结上面所说的,Maven 仓库的优先级就是 私服和远程仓库 的对比,没有其它的仓库类型。为什么这么说是因为,镜像等同远程仓库,而中央其实也是 maven super xml 配置的一个 repository 而已。所以 repostorymirrorcentral 都等同于远程仓库 repository。所以 maven 仓库真正的优先级又可以理解为:
本地仓库 > 私服(profile)> 远程仓库(repository)
 

五、其他问题

maven-metadata.xml 文件

有时候我们更新最新包的时候,会发现最新的包被拉取下来的,但是项目使用的包还是旧的包。所以我们要分析下是什么原因导致的。
Maven Repository Metadata 可用于表示:
元数据文件名是:
以上是 Maven 官网对该文件的解释。我们先大概的了解下 maven-metadata.xml 文件。
其中 lastUpdated 是最中要的一个属性,Maven 更新工程的 jar 包时,会比较 lastUpdated 时间戳值,哪个值更大,就以哪个文件为准。maven-metadata.xml 一共有三个文件:
  1. maven-metadata-local.xml 本地的元数据,Maven install 的时候就会生成。
  1. maven-metadata-snapshots.xml Maven deploy 时会生成,先从远程仓库对应包的 maven-metadata.xml 下载下来,然后修改快照信息后在上传到远程仓库上。
  1. maven-metadata-localhost.xml 远程仓库获取的时候生成 (repository 的 id = localhost),会先跟本地 maven-metadata-local 比较下 lastUpdated 时间戳值,值大用哪个。如果是 Maven 强制更新 的时候(没有强制更新是不会) 会下载远程的 maven-metadata.xml 比较远程、本地、和之前远程保存下来的 maven-metadata 文件。
看下 mvn deploy 的日志信息。
所以有时候 maven 库上的 jar 包已经更新,而我们总是拉取不到 maven 的包原因就是本地的 maven-metadata-local 的 lastUpdated 比较大
解决办法是把 maven-metadata 文件删除,重新拉取 jar 包

参考

Maven系列:全局Settings配置Maven系列:常用插件汇总
mcbilla
mcbilla
一个普通的干饭人🍚
Announcement
type
status
date
slug
summary
tags
category
icon
password
🎉欢迎来到飙戈的博客🎉
-- 感谢您的支持 ---
👏欢迎学习交流👏