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 文件配置一个
mirror
的 mirrorOf
为 central
的镜像就可以替代中央仓库了(镜像的概念下面再说)。远程仓库
需要联网的、由开发人员自己定制的仓库。例如一个公司可能有很多共享的 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 将失去作用。
mirror
的配置语法如下,mirrorOf
表示要替换的 repository
的 id
。例如我们要设置了一个 Maven 中央仓库 http://repo.maven.apache.org/maven2/
的镜像,就需要将该元素设置成 central
,这必须和中央仓库的 id 完全一致为什么配置镜像?
- 一句话,你有的我也有,你没有的我也有。(拥有远程仓库的所有 jar,包括远程仓库没有的 jar)
- 还是一句话,我跑的比你快。(有时候远程仓库获取 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 远程仓库优先级了。
- 从日志信息我们得出这几种 maven 仓库的优先级别为
本地仓库 > 私服 (profile)> 远程仓库(repository)和 镜像 (mirror) > 中央仓库 (central)
- 镜像是一个特殊的配置,其实镜像等同与远程仓库,没有匹配远程仓库的镜像就毫无作用(如 foo2)。
- 总结上面所说的,Maven 仓库的优先级就是 私服和远程仓库 的对比,没有其它的仓库类型。为什么这么说是因为,镜像等同远程仓库,而中央其实也是 maven super xml 配置的一个 repository 而已。所以
repostory
、mirror
、central
都等同于远程仓库repository
。所以 maven 仓库真正的优先级又可以理解为:
本地仓库 > 私服(profile)> 远程仓库(repository)
五、其他问题
maven-metadata.xml 文件
有时候我们更新最新包的时候,会发现最新的包被拉取下来的,但是项目使用的包还是旧的包。所以我们要分析下是什么原因导致的。
Maven Repository Metadata 可用于表示:
元数据文件名是:
以上是 Maven 官网对该文件的解释。我们先大概的了解下 maven-metadata.xml 文件。
其中 lastUpdated 是最中要的一个属性,Maven 更新工程的 jar 包时,会比较 lastUpdated 时间戳值,哪个值更大,就以哪个文件为准。maven-metadata.xml 一共有三个文件:
- maven-metadata-local.xml 本地的元数据,Maven install 的时候就会生成。
- maven-metadata-snapshots.xml Maven deploy 时会生成,先从远程仓库对应包的 maven-metadata.xml 下载下来,然后修改快照信息后在上传到远程仓库上。
- 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 包。
参考
- Author:mcbilla
- URL:http://mcbilla.com/article/068bf4f1-476b-42d1-a277-bcf3530bdbb7
- Copyright:All articles in this blog, except for special statements, adopt BY-NC-SA agreement. Please indicate the source!
Relate Posts