【maven】maven settings.xml 中 mirror 和 repository 的区别

本文解析了Maven中mirror配置的工作原理及匹配过程,并详细介绍了如何通过settings.xml中的mirror配置来替代远程仓库地址。

一、概述

maven的settings.xml文件里面有proxy、server、repository、mirror的配置,在配置仓库地址的时候容易混淆

  1. proxy是服务器不能直接访问外网时需要设置的代理服务,不常用
  2. server是服务器要打包上传到私服时,设置私服的鉴权信息
  3. repository是服务器下载jar包的仓库地址
  4. mirror是用于替代仓库地址的镜像地址

二、源码解析执行流程

2.1》初始化远程仓库

在maven的远程仓库初始化时会执行newRepositorySession方法,会创建mirror、proxy、authentication和其它系统环境信息:

this.mavenRepositorySystem.injectMirror(request.getRemoteRepositories(), request.getMirrors());
this.mavenRepositorySystem.injectProxy(session, request.getRemoteRepositories());
this.mavenRepositorySystem.injectAuthentication(session, request.getRemoteRepositories());

 2.2》遍历注入镜像

在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");
  }

2.3》匹配镜像

在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

四 、实践

4.1》maven 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">

  <pluginGroups></pluginGroups>
  <proxies></proxies>

  <servers>
      <server>
      <id>nexus-releases</id>
      <username>admin</username>
      <password>admin123</password>
    </server>
    <server>
      <id>nexus-snapshots</id>
      <username>admin</username>
      <password>admin123</password>
    </server>
  </servers>

  <mirrors> 
    <mirror> 
      <id>nexus-releases</id> 
      <mirrorOf>nexus-releases</mirrorOf> 
      <url>http://localhost:8081/nexus/content/groups/public</url> 
    </mirror>
    <mirror> 
      <id>nexus-snapshots</id> 
      <mirrorOf>nexus-snapshots</mirrorOf> 
      <url>http://localhost:8081/nexus/content/groups/public-snapshots</url> 
    </mirror> 
  </mirrors> 
 
  <profiles>
   <profile>
      <id>nexus</id>
      <repositories>
        <repository>
          <id>nexus-releases</id>
          <url>http://nexus-releases</url>
          <releases><enabled>true</enabled></releases>
          <snapshots><enabled>true</enabled></snapshots>
        </repository>
        <repository>
          <id>nexus-snapshots</id>
          <url>http://nexus-snapshots</url>
          <releases><enabled>true</enabled></releases>
          <snapshots><enabled>true</enabled></snapshots>
        </repository>
      </repositories>
      <pluginRepositories>
         <pluginRepository>
                <id>nexus-releases</id>
                 <url>http://nexus-releases</url>
                 <releases><enabled>true</enabled></releases>
                 <snapshots><enabled>true</enabled></snapshots>
               </pluginRepository>
               <pluginRepository>
                 <id>nexus-snapshots</id>
                  <url>http://nexus-snapshots</url>
                <releases><enabled>true</enabled></releases>
                 <snapshots><enabled>true</enabled></snapshots>
             </pluginRepository>
         </pluginRepositories>
    </profile>
  </profiles>

  <activeProfiles>
      <activeProfile>nexus</activeProfile>
  </activeProfiles>
 
</settings>

4.2》项目所在pom.xml配置

<distributionManagement>
        <!-- 两个ID必须与 setting.xml中的<server><id>nexus-releases</id></server>保持一致-->
        <repository>
            <id>nexus-releases</id>
            <name>Nexus Release Repository</name>
            <url>http://localhost:8081/nexus/content/repositories/releases</url>
        </repository>
        <snapshotRepository>
            <id>nexus-snapshots</id>
            <name>Nexus Snapshot Repository</name>
            <url>http://localhost:8081/nexus/content/repositories/snapshots</url>
        </snapshotRepository>
    </distributionManagement>

 

Maven Archetype、`<mirror>``<profile>`在Maven的项目管理中各自承担着不同的角色,它们之间存在着一定的关联。 Maven Archetype是一个项目模板工具,用于快速生成项目的基本结构文件。它可以帮助开发者快速搭建项目框架,遵循特定的项目结构规范。 `<mirror>`元素是`settings.xml`中的一个配置项,用于配置镜像仓库。当Maven需要从远程仓库下载依赖时,会根据`<mirror>`的配置,将请求重定向到指定的镜像仓库,从而加快下载速度。 `<profile>`元素也是`settings.xml`中的配置项,用于定义一组配置信息,可以根据不同的环境或条件来激活。`<profile>`可以包含`<repositories>`、`<pluginRepositories>`等配置,用于指定项目的仓库信息。 它们之间的关系主要体现在以下几个方面: - **Archetype与`<mirror>`**:Maven Archetype在生成项目时,可能需要从远程仓库下载模板文件。如果配置了`<mirror>`,Maven会通过镜像仓库来下载这些模板文件,从而加快下载速度。例如,当从Maven中央仓库下载Archetype模板时,如果配置了中央仓库的镜像,Maven会直接从镜像仓库下载。 - **Archetype与`<profile>`**:`<profile>`可以为不同的环境或条件提供不同的仓库配置。当使用Maven Archetype生成项目时,如果激活了特定的`<profile>`,项目会使用该`<profile>`中配置的仓库信息来下载依赖模板文件。例如,在开发环境生产环境中,可以分别定义不同的`<profile>`,每个`<profile>`指定不同的仓库地址,Maven Archetype会根据激活的`<profile>`来选择合适的仓库。 - **`<mirror>`与`<profile>`**:`<mirror>``<profile>`可以结合使用。`<profile>`可以包含`<mirror>`的配置,这样在激活该`<profile>`时,会使用其中配置的镜像仓库。例如,在某个`<profile>`中配置了特定的镜像仓库,当该`<profile>`被激活时,Maven会使用这个镜像仓库来下载依赖。 ### 代码示例 以下是`settings.xml`中`<mirror>``<profile>`的配置示例: ```xml <settings> <!-- 镜像配置 --> <mirrors> <mirror> <id>central-mirror</id> <mirrorOf>central</mirrorOf> <url>http://your-mirror-url.com</url> </mirror> </mirrors> <!-- 配置文件 --> <profiles> <profile> <id>dev-profile</id> <repositories> <repository> <id>dev-repo</id> <url>http://dev-repo-url.com</url> </repository> </repositories> <pluginRepositories> <pluginRepository> <id>dev-plugin-repo</id> <url>http://dev-plugin-repo-url.com</url> </pluginRepository> </pluginRepositories> </profile> </profiles> <!-- 激活配置文件 --> <activeProfiles> <activeProfile>dev-profile</activeProfile> </activeProfiles> </settings> ``` ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值