maven的mirror和repository加载顺序
一、概述
maven的settings.xml文件里面有proxy、server、repository、mirror的配置,在配置仓库地址的时候容易混淆
proxy是服务器不能直接访问外网时需要设置的代理服务,不常用
server是服务器要打包上传到私服时,设置私服的鉴权信息
repository是服务器下载jar包的仓库地址
mirror是用于替代仓库地址的镜像地址
下面查看源码来确定repository和mirror的优先顺序
二、初始化远程仓库
在maven的远程仓库初始化时会执行newRepositorySession方法,会创建mirror、proxy、authentication和其它系统环境信息:
this.mavenRepositorySystem.injectMirror(request.getRemoteRepositories(), request.getMirrors());
this.mavenRepositorySystem.injectProxy(session, request.getRemoteRepositories());
this.mavenRepositorySystem.injectAuthentication(session, request.getRemoteRepositories());
三、遍历注入镜像
在injectMirror方法中:
public void injectMirror(List<ArtifactRepository> repositories, List<Mirror> mirrors) { if ((repositories != null) && (mirrors != null)) { for (ArtifactRepository repository : repositories) { Mirror mirror = getMirror(repository, mirrors); injectMirror(repository, mirror); } } }
遍历repositories,获得mirror然后注入mirror
注:这里不用担心repositories没数据,因为在之前的初始化repositories方法中会判断没有配置"central"中央仓库的时候加入默认仓库
private void injectDefaultRepositories(MavenExecutionRequest request) throws MavenExecutionRequestPopulationException { Set<String> definedRepositories = this.repositorySystem.getRepoIds(request.getRemoteRepositories()); if (!definedRepositories.contains("central")) { try { request.addRemoteRepository(this.repositorySystem.createDefaultRemoteRepository(request)); } catch (Exception e) { throw new MavenExecutionRequestPopulationException("Cannot create default remote repository.", e); } } }
public ArtifactRepository createDefaultRemoteRepository(MavenExecutionRequest request)
throws Exception
{
return createRepository("https://repo.maven.apache.org/maven2", "central", true, "daily", false, "daily", "warn");
}
三、匹配镜像
在getMirror方法中:
public static Mirror getMirror(ArtifactRepository repository, List<Mirror> 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; }
忽略不常用的layout配置,第一个循环优先寻找mirrorOf与repositoryId完全相同的mirror
第二个循环通过规则来匹配mirror,matchPattern的方法:
static boolean matchPattern(ArtifactRepository originalRepository, String pattern)
{
boolean result = false;
String originalId = originalRepository.getId();
if (("*".equals(pattern)) || (pattern.equals(originalId)))
{
result = true;
}
else
{
String[] repos = pattern.split(",");
for (String repo : repos) {
if ((repo.length() > 1) && (repo.startsWith("!")))
{
if (repo.substring(1).equals(originalId))
{
result = false;
break;
}
}
else
{
if (repo.equals(originalId))
{
result = true;
break;
}
if (("external:*".equals(repo)) && (isExternalRepo(originalRepository))) {
result = true;
} else if ("*".equals(repo)) {
result = true;
}
}
}
}
return result;
}
如果是mirrorOf是*号就匹配,如果不是就遍历可能是逗号分隔的mirrorOf值,同时看是否是!号排除的
在找到mirror后会执行injectMirror方法,把匹配的mirror注入到repository里面:
private void injectMirror(ArtifactRepository repository, Mirror mirror) { if (mirror != null) { ArtifactRepository original = createArtifactRepository(repository.getId(), repository.getUrl(), repository.getLayout(), repository .getSnapshots(), repository.getReleases()); repository.setMirroredRepositories(Collections.singletonList(original)); repository.setId(mirror.getId()); repository.setUrl(mirror.getUrl()); if (StringUtils.isNotEmpty(mirror.getLayout())) { repository.setLayout(getLayout(mirror.getLayout())); } } }
四、总结
1、在mirrorOf与repositoryId相同的时候优先是使用mirror的地址
2、mirrorOf等于*的时候覆盖所有repository配置
3、存在多个mirror配置的时候mirrorOf等于*放到最后
4、只配置mirrorOf为central的时候可以不用配置repository
我的settings.xml一般这样设置:
<?xml version="1.0" encoding="UTF-8"?> <settings xmlns="http://maven.apache.org/SETTINGS/1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd"> <localRepository>X:\工具\maven资源\repository</localRepository> <pluginGroups></pluginGroups> <proxies></proxies> <servers></servers> <mirrors> <mirror> <id>nexus-aliyun</id> <name>Nexus aliyun</name> <mirrorOf>central</mirrorOf> <url>http://maven.aliyun.com/nexus/content/groups/public</url> </mirror> <mirror> <id>nexus-mine</id> <name>Nexus mine</name> <mirrorOf>*</mirrorOf> <url>http://xx.xx.xx.xx/nexus/content/groups/public</url> </mirror> </mirrors> <profiles></profiles> </settings>
nexus-aliyun使用阿里云的镜像作为central中央仓库
nexus-mine作为私服,mirrorOf配置为*来提供中央仓库中不存在的jar包