一、概述
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包