乐途乐途
主页
  • 计算机基础

    • TCP/IP协议
    • Linux命令
    • HTTP协议
  • 数据库

    • SQL
    • MySQL 5.7
  • 编程语言

    • C语言
    • Python2
    • Python3
  • 数据格式

    • JSON
    • XML
  • 认证与安全

    • JWT
  • 工具

    • Markdown
  • Git

    • GitFlow
  • Quartz

    • Quartz
  • Java

    • MyBatis
    • Spring
    • Spring MVC
    • Maven 入门
    • Maven 进阶
    • Java 设计模式
  • 缓存

    • Redis
联系
阿里云
主页
  • 计算机基础

    • TCP/IP协议
    • Linux命令
    • HTTP协议
  • 数据库

    • SQL
    • MySQL 5.7
  • 编程语言

    • C语言
    • Python2
    • Python3
  • 数据格式

    • JSON
    • XML
  • 认证与安全

    • JWT
  • 工具

    • Markdown
  • Git

    • GitFlow
  • Quartz

    • Quartz
  • Java

    • MyBatis
    • Spring
    • Spring MVC
    • Maven 入门
    • Maven 进阶
    • Java 设计模式
  • 缓存

    • Redis
联系
阿里云
  • 学习路径
  • 第1章 介绍与核心概念

    • Maven是什么
    • 约定优于配置
  • 第2章 安装与配置

    • 安装与验证
    • settings.xml
    • 本地仓库与镜像
  • 第3章 POM与项目坐标

    • POM
    • GAV坐标
    • packaging
  • 第4章 标准目录布局

    • 标准目录布局
  • 第5章 依赖机制

    • dependencies
    • scope
    • 依赖传递
    • 依赖冲突与调解
    • exclusions
    • optional
    • dependencyManagement
  • 第6章 仓库

    • 仓库体系
    • 本地仓库
    • 远程仓库与镜像
    • 私服
  • 第7章 构建生命周期

    • 生命周期概述
    • clean 生命周期
    • default 生命周期
    • site 生命周期
    • 生命周期与插件绑定
  • 第8章 插件

    • 插件概述
    • maven-compiler-plugin
    • maven-surefire-plugin
    • maven-war-plugin
  • 第9章 继承与聚合

    • parent继承
    • 聚合
    • BOM
    • properties
  • 第10章 属性与资源过滤

    • 资源过滤
    • Profile
  • 第11章 常用命令

    • mvn compile
    • mvn test
    • mvn package
    • mvn clean
    • mvn install
    • mvn dependency:tree
  • 第12章 常见问题与最佳实践

    • 依赖冲突排查
    • 最佳实践

本地仓库与镜像

本章承接"settings.xml",深入讲解 Maven 依赖管理的物理基础设施。理解本地仓库和镜像的配置原理,是解决"依赖下载慢""仓库找不到""构建超时"等实际问题的关键。


核心机制

镜像是仓库的"替身"。当原始仓库访问慢或不可达时,镜像接管请求,提供同样的内容。两句话的潜台词是:

  1. 仓库是依赖的"存放地",分为本地(你电脑上的文件夹)和远程(网络上的服务器)
  2. 镜像是仓库的"替身",当原始仓库访问慢或不可达时,镜像接管请求,提供同样的内容

没有仓库,Maven 的依赖管理就是空中楼阁;没有镜像,国内开发者面对中央仓库的网络延迟会痛不欲生。

本地仓库:Maven 的"本地缓存"

本地仓库(local repository)是 Maven 在你本地磁盘上维护的一个依赖缓存目录。当你第一次构建项目时,Maven 从远程仓库下载所需的 JAR 包、POM 文件和源码,存放到本地仓库。后续构建同一依赖时,直接从本地读取,无需重复下载。

默认位置:

  • Windows:C:\Users\<用户名>\.m2\repository
  • Linux/Mac:~/.m2/repository

物理结构:本地仓库中的文件按照 GAV 坐标 的层级存放。例如 spring-context-5.3.21.jar 的存放路径是:

repository/
└── org/
    └── springframework/
        └── spring-context/
            └── 5.3.21/
                ├── spring-context-5.3.21.jar
                ├── spring-context-5.3.21.pom
                └── spring-context-5.3.21-sources.jar

这种层级结构让 Maven 能通过坐标快速定位文件,也让开发者能直接进目录查看已下载的依赖。

镜像:给仓库配一个"加速器"

Maven 中央仓库(https://repo.maven.apache.org/maven2)位于美国。国内开发者直接访问时,经常遇到下载慢、连接超时的问题。镜像机制允许你配置一个"替身服务器",当 Maven 想去中央仓库下载依赖时,实际请求被转发到镜像服务器。

镜像的核心属性:

属性含义示例
id镜像的唯一标识aliyunmaven
name镜像的可读名称阿里云公共仓库
url镜像服务器的地址https://maven.aliyun.com/repository/public
mirrorOf替哪个原始仓库服务central(代表中央仓库)

mirrorOf 是最关键的属性,它决定了"拦截哪些仓库的请求"。常见取值:

  • central:只拦截中央仓库的请求
  • *:拦截所有仓库的请求(最激进)
  • repo1,repo2:只拦截指定的多个仓库
  • external:*:拦截所有外部仓库,但不拦截本地文件协议的仓库

生活类比:图书馆与图书代购

想象 Maven 的仓库体系是一座图书馆系统:

  • 本地仓库 = 你家的私人书架。你买过的书(下载过的依赖)都放在这里。下次想读同一本书,直接从书架上拿,不用再去图书馆。
  • 中央仓库 = 国家总图书馆。藏书最全,但离你家很远,借一次书要排队、等快递。
  • 镜像 = 你家附近的社区分馆(如阿里云镜像)。它是总图书馆的完整拷贝,但就在你家楼下。你想借书时,系统自动把请求转给社区分馆,当天就能拿到。

如果没有社区分馆(镜像),每次借书都要等一周(下载超时);如果没有私人书架(本地仓库),每次想查同一本书都要重新借(重复下载)。


图示

上图展示了依赖下载的完整时序:

  1. 本地优先:Maven 总是先查本地仓库,命中则直接返回,零网络开销
  2. 镜像代理:本地缺失时,请求发给镜像而非直接访问中央仓库
  3. 回源机制:镜像如果也没有(罕见),会自动向中央仓库回源,开发者无感知
  4. 本地缓存:无论依赖从哪来,下载后都会写入本地仓库,供下次复用

完整示例

场景

飞翔科技的新项目 payroll-service(薪资计算服务)需要引入 Spring Boot 和 MySQL 驱动。小崔第一次执行 mvn compile 时,发现依赖下载极慢,甚至超时失败。白歌诊断后,判断是直连 Maven 中央仓库的网络问题,决定配置阿里云镜像。

操作前:默认配置与问题

小崔的 settings.xml 尚未配置镜像,本地仓库使用默认路径。执行编译:

cd C:\projects\payroll-service
mvn compile

问题输出:

Downloading from central: https://repo.maven.apache.org/maven2/org/springframework/boot/spring-boot-starter/3.2.0/spring-boot-starter-3.2.0.pom
Progress: 1.2 kB/s, 预计剩余时间: 8 分钟...

下载速度只有 1.2 KB/s,一个 20MB 的依赖要下半小时。小崔的第一次编译体验极差。

操作步骤

步骤 1:修改本地仓库路径(可选但推荐)

小崔的 C 盘空间紧张,白歌建议把本地仓库改到 D 盘。编辑 C:\Users\小崔\.m2\settings.xml:

<settings xmlns="http://maven.apache.org/SETTINGS/1.2.0"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.2.0
                              https://maven.apache.org/xsd/settings-1.2.0.xsd">

    <!-- 本地仓库改到 D 盘,避免 C 盘爆满 -->
    <localRepository>D:/maven-repo</localRepository>

    <!-- 配置阿里云镜像,加速依赖下载 -->
    <mirrors>
        <mirror>
            <id>aliyunmaven</id>
            <name>阿里云公共仓库</name>
            <url>https://maven.aliyun.com/repository/public</url>
            <mirrorOf>central</mirrorOf>
        </mirror>
    </mirrors>

</settings>

注意:localRepository 的路径在 Windows 下可以用正斜杠 /,Maven 会自动处理。不要用反斜杠 \,除非转义为 \\。

步骤 2:验证配置生效

小崔再次执行编译:

mvn compile

预期输出:

Downloading from aliyunmaven: https://maven.aliyun.com/repository/public/org/springframework/boot/spring-boot-starter/3.2.0/spring-boot-starter-3.2.0.pom
Downloaded from aliyunmaven: https://maven.aliyun.com/repository/public/org/springframework/boot/spring-boot-starter/3.2.0/spring-boot-starter-3.2.0.pom (3.5 kB at 125 kB/s)

注意输出中的变化:

  • Downloading from 后面的仓库名从 central 变成了 aliyunmaven
  • 下载速度从 1.2 KB/s 提升到 125 KB/s,提速 100 倍

步骤 3:查看本地仓库的物理结构

编译完成后,小崔查看本地仓库,确认依赖已被缓存:

D:/maven-repo/
└── org/
    └── springframework/
        └── boot/
            └── spring-boot-starter/
                └── 3.2.0/
                    ├── spring-boot-starter-3.2.0.jar
                    ├── spring-boot-starter-3.2.0.pom
                    └── _remote.repositories

_remote.repositories 文件记录了该依赖是从哪个仓库下载的,帮助 Maven 判断是否需要更新。

操作结果及分析

配置镜像后,飞翔科技团队的依赖下载体验发生质变:

指标配置前配置后提升
下载源Maven 中央仓库(美国)阿里云镜像(国内)网络路径缩短
下载速度~1 KB/s~100+ KB/s100 倍
首次编译时间30+ 分钟2~3 分钟10 倍
重复编译时间仍要联网检查更新完全本地读取秒级

易错点与常见问题

误区一:mirrorOf 写成 * 导致私服请求也被拦截

错误配置:

<mirror>
    <id>aliyunmaven</id>
    <url>https://maven.aliyun.com/repository/public</url>
    <mirrorOf>*</mirrorOf>   <!-- ❌ 拦截所有仓库 -->
</mirror>

后果:飞翔科技有自己的 Nexus 私服(http://nexus.feixiang.com),用于存放内部私有 JAR。mirrorOf=* 会把私服请求也拦截下来,转发给阿里云。阿里云当然没有飞翔科技的私有 JAR,导致构建报错:

Could not find artifact com.feixiang:internal-sdk:jar:1.0.0 in aliyunmaven

纠正:只拦截中央仓库,放过其他仓库:

<mirrorOf>central</mirrorOf>   <!-- ✅ 只拦截中央仓库 -->

或者,如果团队确实需要所有外部请求都走阿里云,但私服不走,可以用:

<mirrorOf>external:*</mirrorOf>   <!-- ✅ 拦截所有外部仓库,不拦截本地文件协议的私服 -->

误区二:本地仓库路径含中文或空格

错误配置:

<localRepository>C:\Users\小崔\.m2\repository</localRepository>   <!-- ❌ 含中文 -->
<!-- 或 -->
<localRepository>C:\Program Files\maven-repo</localRepository>     <!-- ❌ 含空格 -->

后果:某些旧版 Maven 插件或 Native 库(如 JNI 依赖)在处理路径时,对中文或空格的编码支持不完善,可能导致 FileNotFoundException 或解压失败。

纠正:使用无中文、无空格的纯英文路径:

<localRepository>D:/maven-repo</localRepository>   <!-- ✅ -->

误区三:多个镜像配置导致优先级混乱

错误配置:小崔从网上复制了一段配置,里面写了两个镜像:

<mirrors>
    <mirror>
        <id>aliyun</id>
        <url>https://maven.aliyun.com/repository/public</url>
        <mirrorOf>central</mirrorOf>
    </mirror>
    <mirror>
        <id>huawei</id>
        <url>https://repo.huaweicloud.com/repository/maven/</url>
        <mirrorOf>central</mirrorOf>
    </mirror>
</mirrors>

后果:两个镜像的 mirrorOf 都是 central,Maven 只会使用第一个匹配的镜像(aliyun),第二个 huawei 实际上永远不会被用到。小崔以为配置了"双保险",实际只是冗余。

纠正:如果确实需要多镜像备份(如主镜像故障时自动切换),应该使用仓库管理器(如 Nexus、Artifactory)在服务端做聚合,而不是在客户端配置多个 mirror。


小结

本地仓库是 Maven 的本地依赖缓存,默认位于 ~/.m2/repository,可通过 settings.xml 中的 localRepository 自定义路径。镜像是远程仓库的替身服务器,通过 mirrorOf 拦截原始仓库的请求,转发到更快的镜像地址。国内开发者配置阿里云镜像,是解决依赖下载慢的标准做法。

本章与全局的关系:本章完成了 Maven 环境配置的最后一块拼图——依赖的存储和下载加速。下一章"POM"将进入项目核心,讲解 pom.xml 如何定义项目的"DNA",以及 Maven 如何通过坐标系统唯一标识一个项目。

上一页
settings.xml