在配置Maven的setting.xml文件时,里面会有mirror元素和repository元素,前者时镜像配置,后者是库的配置。
什么是镜像,简明扼要的说,如果Y库中的所有东西,都能从X库中得到,那么X就是Y的镜像。
如图:
配置了mirror的话,就会从B中获取资源,而如果没有配置mirror,用户只能从A中获取获取资源,而如果用户此时对A的网络情况不太好,那么下载资源的速度会很慢,影响开发效率。这个时候,mirror更像是一个拦截器的存在,把对A的请求全部拦截发往B。
我们可以从Maven的源代码中窥探一下这两者的关系:
@Deprecated
public ArtifactRepository getMirrorRepository(ArtifactRepository repository) {
Mirror mirror = mirrorSelector.getMirror(repository, legacySupport.getSession().getSettings().getMirrors());
if (mirror != null) {
String id = mirror.getId();
if (id == null) {
// TODO: this should be illegal in settings.xml
id = repository.getId();
}
log.debug("Using mirror: " + mirror.getUrl() + " (id: " + id + ")");
repository = artifactRepositoryFactory.createArtifactRepository(id, mirror.getUrl(),
repository.getLayout(), repository.getSnapshots(),
repository.getReleases());
}
return repository;
}
public Mirror getMirror(ArtifactRepository repository, List mirrors) {
String repoId = repository.getId();
if (repoId != null && mirrors != null) {
for (Mirror mirror : mirrors) {
if (repoId.equals(mirror.getMirrorOf()) && matchesLayout(repository, mirror)) {
return mirror;
}
}
for (Mirror mirror : mirrors) {
if (matchPattern(repository, mirror.getMirrorOf()) && matchesLayout(repository, mirror)) {
return mirror;
}
}
}
return null;
}
从上面这两段代码中可以看出,
1.它会根据repository去寻找对应的mirror,如果没有找到,则直接返回使用这个repository的配置,如果找到了,则通过createArtifactRepository方法使用这个mirror中的url新构造一个repository,来请求资源。
在两个for循环中,分别是对mirror和repository的匹配,
第一种情况是针对单个id的匹配,mirror中mirrorOf的值等于repository的id,并且layout匹配(通常情况下layout是默认的,不会进行特殊配置),mirrorOf这个元素的意思很明显,字面意思就是指谁的mirror,也就是对谁的镜像,当mirrorOf的值和repository的id匹配时,那么就使用这个mirror。
第二种情况是针对范围的匹配,先看看matchPattern函数的内容:
static boolean matchPattern(ArtifactRepository originalRepository, String pattern) {
boolean result = false;
String originalId = originalRepository.getId();
//首先匹配*号,如果mirrorOf是*号,就用当前的镜像
//或者如果当前的mirrorOf和repository的id一样也返回(这在前面的for循环处理过,所以这种情况基本不会出现)
if (WILDCARD.equals(pattern) || pattern.equals(originalId)) {
result = true;
} else {
//其次mirrorOf支持多个用逗号隔开,这里先拆分,逐个循环
String[] repos = pattern.split(",");
for (String repo : repos) {
//repo支持!(感叹号)来屏蔽一个repository的Id,这里先判断如果是排除的,就return false
if (repo.length() > 1 && repo.startsWith("!")) {
if (repo.substring(1).equals(originalId)) {
// explicitly exclude. Set result and stop processing.
result = false;
break;
}
}
//逗号隔开中的一个值和repository的id一样就返回true
else if (repo.equals(originalId)) {
result = true;
break;
}
//检查外部匹配external:*
else if (EXTERNAL_WILDCARD.equals(repo) && isExternalRepo(originalRepository)) {
result = true;
}
//最后检查*匹配
else if (WILDCARD.equals(repo)) {
result = true;
}
}
}
return result;
}
系统中定义了一个全匹配*和外部全匹配external:*
private static final String WILDCARD = "*";
private static final String EXTERNAL_WILDCARD = "external:*";
从这段代码可以得到如下规则: