mirror镜像和repository远程仓库
mirror就是镜像,主要提供一个方便切换远程仓库地址的途径。
比如,上班的时候在公司,用电信的网络,连的是电信的仓库。
回到家后,是联通的网络,我想连联通的仓库,就可以通过mirror配置,统一把我工程里的仓库地址都改成联通的,而不用到具体工程配置文件里一个一个地改地址。
《maven实战》里面解释的镜像:
mirrorof的官方文档解释
https://maven.apache.org/guides/mini/guide-mirror-settings.html
可以理解为,mirrorof就是镜像规则。这个规则,将镜像mirror(setting.xml的设置)和远程仓库repository(pom.xml的repository设置)关联起来。哪个远程仓库被哪个镜像所替代。
如果还是没能理解,可以看看这两篇博客。
maven的setting配置文件中mirror和repository的区别
- ==如果maven setting.xml中配置了镜像mirror , 而镜像mirror配置里mirrorof的规则,匹配到目标仓库时 ,
maven认为目标仓库被镜像了, 不会再去被镜像仓库下载依赖jar包, 而是直接去镜像仓库下载。即maven里面设置的repository会被setting.xml里面的mirror所屏蔽。== - <mirrorof></mirrorof>的值为匹配repository仓库的id。也可以使用高级配置,如通配符*,否定符!。
<mirror>
<id>aliyun-maven</id>
<name>aliyun maven</name>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
<mirrorOf>repotest</mirrorOf>
</mirror>
镜像配置的规则 <mirrorOf>repotest</mirrorOf> 匹配到目标仓库 <id>repotest</id>,所以maven认为目标仓库repotest被镜像了, 不再去https://repo.maven.apache.org/maven2/地址下载jar包,而是去镜像仓库http://maven.aliyun.com/nexus/content/groups/public/下载jar包。
<repositories>
<repository>
<id>repotest</id>
<url>https://repo.maven.apache.org/maven2/</url>
</repository>
</repositories>
我们通过下面例子去理解镜像mirror和仓库repository和mirrorof的含义
默认中央仓库
先把setting.xml里面的mirror配置去掉,保持<mirrors></mirrors>节点为空,然后一步一步开始实践,了解这三个的含义。
# 在pom.xml配置以下内容:
<repositories>
<repository>
<id>cloudera</id>
<url>https://repository.cloudera.com/artifactory/cloudera-repos/</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-client</artifactId>
<version>2.6.0-dad1-cdh5.14.2</version>
</dependency>
</dependencies>
- 可以从idea的解析maven依赖的顺序,观察出:先去cloudera仓库找这个jar包。
- 发现在cloudera仓库没找这个jar包。所以去默认中央仓库去找这个jar包。
从上面这个例子,我们可以这么理解,默认情况下,maven下面的pom.xml的中央仓库,缺省了模板仓库id为central
,url为maven中央仓库url:https://repo.maven.apache.org/maven2/。
# 默认中央仓库
<repositories>
<repository>
<id>central</id>
<url>https://repo.maven.apache.org/maven2/</url>
</repository>
</repositories>
修改默认中央仓库地址
我们可以在pom.xml,设置一个id为central和url来覆盖缺省 id = central的url。
<repositories>
<repository>
<id>central</id>
<url>https://repository.cloudera.com/artifactory/cloudera-repos/</url>
</repository>
</repositories>
然后下载mysql驱动,此时发现,下载mysql驱动失败。因为默认中央仓库的url被重写成cloudera公司的目标仓库。但cloudera公司自己搭建的仓库里面并没有这个jar包。所以pom.xml找不到这个jar包。
仓库的优先级
先从repository找出所有id的名字,看看他们有没有被setting.xml配置的mirror的mirrorof规则所匹配(即被镜像到),如果有,将repository的url地址改成mirror配置的url,替换完地址后。再依次检索repositorys下面所有的repository下载相应的jar。
例子1:
<mirrorOf>central</mirrorOf>
<mirror>
<id>alimaven</id>
<name>aliyun maven</name>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
<mirrorOf>central</mirrorOf>
</mirror>
<repositories>
<repository>
<id>central</id>
<url>https://repo.maven.apache.org/maven2/</url>
</repository>
<repository>
<id>cloudera</id>
<url>https://repository.cloudera.com/artifactory/cloudera-repos/</url>
</repository>
</repositories>
- 镜像url替换后会变成下面所示:
<repositories>
<repository>
<id>central</id>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
</repository>
<repository>
<id>cloudera</id>
<url>https://repository.cloudera.com/artifactory/cloudera-repos/</url>
</repository>
</repositories>
- 然后依次从central仓库,寻找jar包,如果找不到则到cloudera仓库寻找jar。
- 可以通过hadoop-client这个只有cloudera仓库有的jar,而阿里云没有。去看看maven寻找jar包的过程。
<dependencies>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-client</artifactId>
<version>2.6.0-mr1-cdh5.14.2</version>
</dependency>
</dependencies>
例子2:
<mirrorOf>central</mirrorOf>加上<mirrorOf>*</mirrorOf>
pom.xml的设置:
<repositories>
<repository>
<id>cloudera</id>
<url>https://repository.cloudera.com/artifactory/cloudera-repos/</url>
</repository>
<repository>
<id>central</id>
<url>https://arepository.cloudera.com/artifactory/cloudera-repos/</url>
</repository>
</repositories>
加上setting.xml的设置:
<mirror>
<id>aliyun-maven</id>
<name>aliyun maven</name>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
<mirrorOf>central</mirrorOf>
</mirror>
<mirror>
<id>central-Repository</id>
<name>Maven central Repository</name>
<url>https://repo1.maven.org/maven2/</url>
<mirrorOf>*</mirrorOf>
</mirror>
# <mirrorOf>central</mirrorOf> 匹配到远程仓库 <id>central</id>,所以远程仓url替换成mirror的url;
# 因为<id>central</id>已经被mirror的url替换了,就不再镜像了;
# <mirrorOf>*</mirrorOf> 替换 <id>cloudera</id>的url。
最终的目标仓库:
<repositories>
<repository>
<id>cloudera</id>
<url>https://repo1.maven.org/maven2</url>
</repository>
<repository>
<id>central</id>
<url>http://maven.aliyun.com/nexus/content/groups/public//</url>
</repository>
</repositories>
所以一般来说setting.xml只需要配置一个central的镜像规则就好了,一般就是阿里云就好了,然后需要其他远程仓库,就手动在pom.xml里面加上repository,但不是这个第三方的仓库就不要把repository的id写成central。不然就被镜像的规则匹配到了,url被替换成阿里云的了。
setting.xml里面的mirror,可以写多个,但mirrorof的规则要从匹配范围小到大写。同时写多个mirrorof的内容为central的意义为0,因为只有其中第一个mirror生效。
镜像搭配远程仓库
一般setting.xml内容为:
<mirrors>
<mirror>
<id>aliyun-maven</id>
<name>aliyun maven</name>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
<mirrorOf>central</mirrorOf>
</mirror>
</mirrors>
假设某个jar包,阿里云镜像没有的jar,把可以下载这个jar包的远程仓库,补充到pom.xml就好了。如:
<repositories>
<repository>
<id>cloudera</id>
<url>https://repository.cloudera.com/artifactory/cloudera-repos/</url>
</repository>
</repositories>
有时公司搭建了内网,只能从私服下载jar包,这时maven项目,pom.xml的repository都是各个私服的url。
(假设都可以在阿里云仓库找到这些jar包,记住这里是假设所有的可以在阿里云的https://maven.aliyun.com/repository/central下载到!!!)回到家里,可以将阿里云的镜像规则设置成 <mirrorOf>*</mirrorOf>,则强制所有远程仓库都到这个镜像下载url。解决了不需要修改pom.xml。
<mirrors>
<mirror>
<id>aliyun-maven</id>
<name>aliyun maven</name>
<url>https://maven.aliyun.com/repository/central</url>
<mirrorOf>*</mirrorOf>
</mirror>
</mirrors>
如果项目里面有些jar包在https://maven.aliyun.com/repository/central仓库找不到,那么setting.xml的mirrorOf 设置成*就不合适了。应该将 <url>https://maven.aliyun.com/repository/central</url>设置成<mirrorOf>center</mirrorOf>,然后未找到的jar包再设置<mirrorOf>repository_name</mirrorOf>实现代理。
一般项目里面,我们应该如何正确设置repositories和国内镜像呢
当我们项目里面需要设置第三方的仓库时,如cloudera的仓库,那么建议<repositories>第一个先写上<repository>仓库的id为center,再写第三方的repository仓库的id和url。这样项目里的jar的下载顺序是从center的中央仓库(如果我们配置了国内镜像则从国内仓库)下载,如果找不到再轮到这个第三方的仓库。避免很多jar包在第三方仓库找不到然后再去center的下载,很慢,我们应该让依赖首先去中央仓库查找,找不到再去第三方仓库找。
下面是我的配置
pom.xml
<repositories>
<repository>
<id>central</id>
<url>https://maven.aliyun.com/repository/central</url>
</repository>
<repository>
<id>cloudera</id>
<url>https://repository.cloudera.com/artifactory/cloudera-repos/</url>
</repository>
</repositories>
setting.xml
<mirror>
<id>aliyunmaven</id>
<mirrorOf>center</mirrorOf>
<name>阿里云公共仓库</name>
<url>https://maven.aliyun.com/repository/central</url>
</mirror>
这个配置,下载依赖的流程为:
- 将repository中id为center的url替换成setting.xml中mirrorOf为center的url。(因为repository中id为center和setting.xml中mirrorOf为center所匹配,所以会将mirror的id为aliyunmaven的url替换掉pom里面id为center的repository。)
- 下载依赖时,先从central仓库下载,如果找不到则从cloudera的repository仓库查找。
有同学会有疑问:
pom.xml 这样写可不可以?
<repositories>
<repository>
<id>cloudera</id>
<url>https://repository.cloudera.com/artifactory/cloudera-repos/</url>
</repository>
</repositories>
答案是可以的,但是如果seting.xml里面没有配置国内镜像,那么从cloudera仓库里面查找镜像,找不到镜像,则从默认id为center的中央仓库地址https://repo1.maven.org/maven2查找镜像,下载速度会很慢,且下载顺序是先cloudera仓库再center仓库,这样下载速度会比较慢,防止有些人没有在setting.xml设置国内中央仓库的镜像,还是建议第一个repository的id为center,url为国内的镜像,一举两得。