Maven 国内源配置指南(2026 版)
📅 2026-05-15 | 🏷️ Maven, Gradle, 信创, DevOps | 📖 阅读约 12 分钟
前言
“Could not resolve dependencies”,这大概是每个 Java 开发者在国内网络环境下更不想看到的错误。
Maven Central 在国内访问速度慢、不稳定,尤其在企业内网和信创环境下,配置国内镜像源几乎是项目初始化的第一步。但你真的会配吗?镜像优先级怎么算?私服和镜像怎么共存?Gradle 的配置和 Maven 有什么不同?
这篇文章给你一个完整的、可直接复制粘贴的配置方案,覆盖 Maven、Gradle、私服、代理、信创环境,2026 年当前公开版。
一、为什么需要国内镜像
Maven Central(https://repo.maven.apache.org/maven2)物理上在美国,国内访问存在以下问题:
- 延迟高:HTTPS 握手 + TCP 往返,单次请求 500ms-2s
- 不稳定:国际链路抖动,下载大文件容易中断
- 带宽受限:高峰期下载速度可能只有几十 KB/s
- 安全合规:信创/政企环境不允许直接访问外网
国内镜像源同步了 Maven Central 的所有包,物理上在国内,访问速度提升 10-100 倍。
Maven 的依赖解析遵循下限路径优先原则。当同一个依赖存在多个版本时,Maven 会在依赖树中选择深度更浅(路径下限)的那个版本。如果深度相同,则按 POM 中声明的顺序选择第一个。
形式化地说,对于依赖树中的节点 D,其解析版本为所有候选版本中深度下限的那个。因此直接声明的依赖优先级高于传递依赖。
二、Maven 配置
2.1 settings.xml 完整配置
将以下内容保存到 ~/.m2/settings.xml(全局配置)或 $MAVEN_HOME/conf/settings.xml(安装级别):
<?xml version="1.0" encoding="UTF-8"?>
<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">
<!-- 本地仓库路径(可选,默认 ~/.m2/repository) -->
<localRepository>${user.home}/.m2/repository</localRepository>
<mirrors>
<!--
阿里云 Maven 镜像(推荐,最稳定,同步频率高)
https://developer.aliyun.com/mirror/maven
-->
<mirror>
<id>aliyun</id>
<name>Aliyun Maven Mirror</name>
<url>https://maven.aliyun.com/repository/public</url>
<mirrorOf>central</mirrorOf> <!-- 只代理 central 仓库 -->
</mirror>
<!--
华为云 Maven 镜像
https://mirrors.huaweicloud.com/
-->
<!-- <mirror>
<id>huawei</id>
<name>Huawei Maven Mirror</name>
<url>https://repo.huaweicloud.com/repository/maven/</url>
<mirrorOf>central</mirrorOf>
</mirror> -->
<!--
腾讯云 Maven 镜像
https://mirrors.cloud.tencent.com/
-->
<!-- <mirror>
<id>tencent</id>
<name>Tencent Maven Mirror</name>
<url>https://mirrors.cloud.tencent.com/nexus/repository/maven-public/</url>
<mirrorOf>central</mirrorOf>
</mirror> -->
</mirrors>
<profiles>
<profile>
<id>aliyun-repos</id>
<!-- 激活条件 -->
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<!-- 仓库配置 -->
<repositories>
<!-- 阿里云公共仓库 -->
<repository>
<id>aliyun-public</id>
<name>Aliyun Public Repository</name>
<url>https://maven.aliyun.com/repository/public</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
<updatePolicy>daily</updatePolicy> <!-- SNAPSHOT 每天更新一次 -->
</snapshots>
</repository>
<!-- Spring 官方仓库(阿里云镜像) -->
<repository>
<id>aliyun-spring</id>
<name>Aliyun Spring Repository</name>
<url>https://maven.aliyun.com/repository/spring</url>
<releases><enabled>true</enabled></releases>
<snapshots><enabled>false</enabled></snapshots>
</repository>
</repositories>
<!-- 插件仓库 -->
<pluginRepositories>
<pluginRepository>
<id>aliyun-plugin</id>
<name>Aliyun Plugin Repository</name>
<url>https://maven.aliyun.com/repository/public</url>
</pluginRepository>
</pluginRepositories>
</profile>
</profiles>
<!-- 激活 profile -->
<activeProfiles>
<activeProfile>aliyun-repos</activeProfile>
</activeProfiles>
</settings>2.2 mirror 和 repository 的区别与优先级
这是很多人搞混的地方:
当 Maven 需要下载依赖时:
1. 先检查本地仓库(~/.m2/repository)
2. 如果没有,再从 effective POM/settings 汇总出的远程仓库中查找
3. 对每个远程仓库,先按 <mirrorOf> 匹配 mirror;匹配到了就请求镜像地址
4. mirror 不是“备用源列表”:同一个仓库命中哪个 mirror,由 mirrorOf 匹配规则和声明顺序决定
关键:<mirrorOf>central</mirrorOf> 只代理 Maven Central
<mirrorOf>*</mirrorOf> 代理所有仓库(慎用!会覆盖私服地址)推荐配置:<mirrorOf>central</mirrorOf>,只镜像中央仓库,其他仓库(如私服)正常访问。
2.3 私服配置与镜像共存
企业项目通常有 Nexus/Artifactory 私服,需要和国内镜像共存:
<!-- settings.xml -->
<mirrors>
<!-- 镜像只代理中央仓库,不要用 * -->
<mirror>
<id>aliyun</id>
<url>https://maven.aliyun.com/repository/public</url>
<mirrorOf>central</mirrorOf>
</mirror>
</mirrors>
<profiles>
<profile>
<id>enterprise</id>
<repositories>
<!-- 私服:公司内部包 -->
<repository>
<id>company-releases</id>
<name>Company Releases</name>
<url>https://nexus.company.com/repository/maven-releases/</url>
<releases><enabled>true</enabled></releases>
<snapshots><enabled>false</enabled></snapshots>
</repository>
<repository>
<id>company-snapshots</id>
<name>Company Snapshots</name>
<url>https://nexus.company.com/repository/maven-snapshots/</url>
<releases><enabled>false</enabled></releases>
<snapshots><enabled>true</enabled></snapshots>
</repository>
<!-- 中央仓库(被阿里云镜像代理) -->
<repository>
<id>central</id>
<url>https://repo.maven.apache.org/maven2</url>
</repository>
</repositories>
</profile>
</profiles>
<!-- 注意:distributionManagement 不能写在 settings.xml 里,发布地址应写在项目 pom.xml -->
<!-- 私服需要认证 -->
<servers>
<server>
<id>company-releases</id>
<username>${env.NEXUS_USER}</username> <!-- 用环境变量,不要硬编码 -->
<password>${env.NEXUS_PASS}</password>
</server>
<server>
<id>company-snapshots</id>
<username>${env.NEXUS_USER}</username>
<password>${env.NEXUS_PASS}</password>
</server>
</servers>发布到私服的地址放在项目 pom.xml:
<distributionManagement>
<repository>
<id>company-releases</id>
<url>https://nexus.company.com/repository/maven-releases/</url>
</repository>
<snapshotRepository>
<id>company-snapshots</id>
<url>https://nexus.company.com/repository/maven-snapshots/</url>
</snapshotRepository>
</distributionManagement>id 必须和 settings.xml 里的 <server><id>...</id></server> 一致,这样 Maven 发布时才能拿到对应凭证。
2.4 代理配置
企业内网通常需要通过 HTTP 代理访问外网:
<!-- settings.xml -->
<proxies>
<proxy>
<id>http-proxy</id>
<active>true</active>
<protocol>http</protocol>
<host>proxy.company.com</host>
<port>8080</port>
<!-- 不需要代理的地址(内网地址) -->
<nonProxyHosts>localhost|127.0.0.1|nexus.company.com|*.company.com</nonProxyHosts>
</proxy>
<proxy>
<id>https-proxy</id>
<active>true</active>
<protocol>https</protocol>
<host>proxy.company.com</host>
<port>8080</port>
<nonProxyHosts>localhost|127.0.0.1|nexus.company.com|*.company.com</nonProxyHosts>
</proxy>
</proxies>也可以通过 JVM 参数配置:
# 命令行设置代理
mvn clean install \
-Dhttps.proxyHost=proxy.company.com \
-Dhttps.proxyPort=8080 \
-Dhttp.nonProxyHosts="localhost|127.0.0.1|*.company.com"三、Gradle 配置
3.1 init.gradle 全局配置
创建 ~/.gradle/init.gradle 文件,对所有项目生效:
// ~/.gradle/init.gradle
allprojects {
repositories {
// 移除默认的 mavenCentral()
// 阿里云镜像(优先)
maven {
name 'aliyun'
url 'https://maven.aliyun.com/repository/public'
allowInsecureProtocol false
}
// 华为云镜像(备用)
maven {
name 'huawei'
url 'https://repo.huaweicloud.com/repository/maven/'
allowInsecureProtocol false
}
// 保留原始 Maven Central 作为最终兜底
mavenCentral()
}
// 插件仓库
buildscript {
repositories {
maven {
name 'aliyun-plugin'
url 'https://maven.aliyun.com/repository/public'
}
mavenCentral()
}
}
}
// Settings 插件仓库(Gradle 7+)
settingsEvaluated { settings ->
settings.pluginManagement {
repositories {
maven {
name 'aliyun-plugin'
url 'https://maven.aliyun.com/repository/public'
}
gradlePluginPortal()
}
}
}3.2 build.gradle 仓库配置(Groovy DSL)
// build.gradle
repositories {
// 阿里云镜像
maven {
url 'https://maven.aliyun.com/repository/public'
}
// Spring 仓库镜像
maven {
url 'https://maven.aliyun.com/repository/spring'
}
// 公司私服
maven {
url 'https://nexus.company.com/repository/maven-releases/'
credentials {
username = findProperty('nexus.user') ?: System.getenv('NEXUS_USER')
password = findProperty('nexus.pass') ?: System.getenv('NEXUS_PASS')
}
}
// 最终兜底
mavenCentral()
}3.3 build.gradle.kts 仓库配置(Kotlin DSL)
// build.gradle.kts
repositories {
maven("https://maven.aliyun.com/repository/public")
maven("https://maven.aliyun.com/repository/spring")
maven {
url = uri("https://nexus.company.com/repository/maven-releases/")
credentials {
username = project.findProperty("nexus.user")?.toString()
?: System.getenv("NEXUS_USER")
password = project.findProperty("nexus.pass")?.toString()
?: System.getenv("NEXUS_PASS")
}
}
mavenCentral()
}3.4 Gradle 7+ settings.gradle.kts 配置
// settings.gradle.kts
pluginManagement {
repositories {
maven("https://maven.aliyun.com/repository/public")
maven("https://maven.aliyun.com/repository/gradle-plugin")
gradlePluginPortal()
}
}
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) // 统一管理仓库
repositories {
maven("https://maven.aliyun.com/repository/public")
maven("https://maven.aliyun.com/repository/spring")
mavenCentral()
}
}
rootProject.name = "my-project"3.5 Gradle 加速配置
# gradle.properties
# 启用构建缓存
org.gradle.caching=true
# 并行编译
org.gradle.parallel=true
# 增加 JVM 内存
org.gradle.jvmargs=-Xmx4g -XX:+HeapDumpOnOutOfMemoryError
# 配置缓存(Gradle 8+)
org.gradle.configuration-cache=true四、Nexus 私服搭建成熟实践
4.1 Nexus 3 Docker 部署
# docker-compose.yml
version: '3.8'
services:
nexus:
image: sonatype/nexus3:3.75.0
container_name: nexus3
ports:
- "8081:8081"
volumes:
- nexus-data:/nexus-data
environment:
- INSTALL4J_ADD_VM_PARAMS=-Xms1g -Xmx4g
restart: unless-stopped
volumes:
nexus-data:部署后配置:
- 访问:
http://nexus-server:8081,初始密码在/nexus-data/admin.password - 创建仓库:
| 仓库类型 | 名称 | 用途 | 代理地址 |
|---|---|---|---|
| 代理仓库 | maven-aliyun | 代理阿里云镜像 | https://maven.aliyun.com/repository/public |
| 宿主仓库 | maven-releases | 存放内部正式发布包 | — |
| 宿主仓库 | maven-snapshots | 存放快照版本 | — |
| 组合仓库 | maven-public | 聚合以上三个,对外暴露 | — |
maven-public 中的成员顺序很重要:将 maven-releases 和 maven-snapshots 放在更前面,maven-aliyun 放在末尾。这样优先从私服获取,找不到才去代理仓库拉取。4.2 Nexus 仓库权限与安全
安全配置要点:
1. 禁用匿名访问(Administration → Security → Anonymous Access → 禁用)
2. 创建专用的 CI/CD 账号,只给 nx-deploy 权限
3. 开发者账号使用 LDAP/AD 集成认证
4. 定期清理快照版本(Administration → Tasks → Create task → Cleanup Service)
5. 开启 HTTPS(Nginx 反向代理 + Let's Encrypt)4.3 Nexus 与阿里云镜像的联动策略
开发机和 CI 只配置 Nexus 组仓库。内部正式包与快照包由宿主仓库提供,外部依赖通过代理仓库缓存。上游地址应按组织的供应链策略选择,并配置 HTTPS、内容校验、组件治理和出站访问控制;不能假定某个镜像站与 Maven Central 始终同步一致。
五、信创环境特殊配置
5.1 内网离线环境的本地仓库搭建
在完全离线的信创环境中,需要搭建本地 Maven 仓库。
方案一:Nexus 离线初始化
# 从有网环境同步依赖到本地目录
mvn dependency:go-offline -Dmaven.repo.local=/opt/maven-repo
# 或使用 rsync 同步整个仓库
rsync -avz --progress user@online-host:~/.m2/repository/ /opt/maven-repo/
# 然后将 /opt/maven-repo 导入 Nexus(通过 Nexus REST API 或直接复制到 nexus-data)方案二:直接使用本地文件仓库
<!-- settings.xml - 离线环境 -->
<profiles>
<profile>
<id>offline</id>
<repositories>
<repository>
<id>local-repo</id>
<url>file:///opt/maven-repo</url> <!-- 本地文件路径 -->
<releases><enabled>true</enabled></releases>
<snapshots><enabled>true</enabled></snapshots>
</repository>
</repositories>
</profile>
</profiles>
<activeProfiles>
<activeProfile>offline</activeProfile>
</activeProfiles>方案三:Maven Wrapper + 本地仓库打包
# 在有网环境打包容器镜像(包含 Maven + 本地仓库)
# Dockerfile
FROM maven:3.9.9-eclipse-temurin-21
COPY local-repo /opt/maven-repo
COPY settings-offline.xml /root/.m2/settings.xml
# 这样 CI/CD 环境直接使用此镜像,无需外网- 国产操作系统(麒麟、统信)的默认 JDK 版本可能较低,建议手动安装 JDK 17/21
- ARM 架构(鲲鹏/飞腾)需要确认 native 依赖有对应的
aarch64版本 - 离线环境的 SNAPSHOT 更新策略应设为
never,避免无意义的远程检查
5.2 国产 CPU 架构的 native 依赖处理
信创环境常用 ARM(鲲鹏/飞腾)或 MIPS(龙芯)架构,native 依赖需要特殊处理:
<!-- 根据架构选择 native 依赖 -->
<profiles>
<!-- 鲲鹏 ARM64 -->
<profile>
<id>aarch64</id>
<activation>
<os>
<arch>aarch64</arch>
</os>
</activation>
<properties>
<os.detected.classifier>linux-aarch64</os.detected.classifier>
</properties>
</profile>
<!-- x86_64 -->
<profile>
<id>x86_64</id>
<activation>
<os>
<arch>amd64</arch>
</os>
</activation>
<properties>
<os.detected.classifier>linux-x86_64</os.detected.classifier>
</properties>
</profile>
</profiles><!-- 依赖中使用 classifier -->
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-transport-native-epoll</artifactId>
<version>4.1.115.Final</version>
<classifier>${os.detected.classifier}</classifier>
</dependency>常见 native 依赖清单:
| 依赖 | 说明 | ARM64 支持 |
|---|---|---|
netty-transport-native-epoll | Netty 高性能网络 | ✅ |
osgi-core | OSGi 框架 | ✅ |
sqlite-jdbc | SQLite 驱动 | ✅ |
grpc-netty-shaded | gRPC 网络层 | ✅ |
conscrypt-openjdk | TLS 加速 | ⚠️ 需验证版本 |
六、常见问题排查
6.1 Could not resolve dependencies 排查流程
1. 检查网络连接
curl -I https://maven.aliyun.com/repository/public
2. 检查 settings.xml 位置是否正确
mvn help:effective-settings # 查看生效的配置
3. 检查仓库配置是否生效
mvn help:effective-pom # 查看生效的 POM
4. 检查镜像是否覆盖了私服
# 如果 <mirrorOf>*</mirrorOf>,所有请求都会被镜像拦截!
5. 强制更新快照
mvn clean install -U # -U 强制更新 SNAPSHOT
6. 清理本地缓存
rm -rf ~/.m2/repository/com/example/broken-artifact
mvn clean install
7. 开启调试日志
mvn clean install -X # 详细日志,可以看到下载请求的完整 URL6.2 版本冲突解决
# 查看依赖树
mvn dependency:tree -Dincludes=com.google.guava:guava
# 分析冲突
mvn dependency:analyze
# 排除传递依赖<dependency>
<groupId>com.example</groupId>
<artifactId>some-library</artifactId>
<version>1.0.0</version>
<exclusions>
<exclusion>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId> <!-- 排除旧版本 guava -->
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>33.4.0-jre</version> <!-- 使用指定版本 -->
</dependency>Gradle 版本冲突解决:
// build.gradle
configurations.all {
resolutionStrategy {
// 强制使用指定版本
force 'com.google.guava:guava:33.4.0-jre'
// 失败快速模式(遇到冲突立即报错)
failOnVersionConflict()
}
}6.3 SNAPSHOT 更新策略
<!-- 控制 SNAPSHOT 更新频率 -->
<repository>
<id>snapshots</id>
<url>https://nexus.company.com/repository/maven-snapshots/</url>
<snapshots>
<enabled>true</enabled>
<updatePolicy>daily</updatePolicy>
<!-- always: 每次构建都检查
daily: 每天检查一次(默认)
interval:X: 每 X 分钟检查
never: 从不更新(离线模式) -->
</snapshots>
</repository># 命令行强制更新
mvn clean install -U
# 离线模式(不检查远程仓库)
mvn clean install -o七、成熟实践
7.1 settings.xml 模板
<?xml version="1.0" encoding="UTF-8"?>
<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">
<localRepository>${user.home}/.m2/repository</localRepository>
<mirrors>
<mirror>
<id>aliyun</id>
<name>Aliyun Maven Mirror</name>
<url>https://maven.aliyun.com/repository/public</url>
<mirrorOf>central</mirrorOf>
</mirror>
</mirrors>
<servers>
<!-- 私服认证:使用环境变量 -->
<server>
<id>company-releases</id>
<username>${env.NEXUS_USER}</username>
<password>${env.NEXUS_PASS}</password>
</server>
<server>
<id>company-snapshots</id>
<username>${env.NEXUS_USER}</username>
<password>${env.NEXUS_PASS}</password>
</server>
</servers>
<profiles>
<profile>
<id>default-repos</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<repositories>
<repository>
<id>aliyun-public</id>
<url>https://maven.aliyun.com/repository/public</url>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>aliyun-plugin</id>
<url>https://maven.aliyun.com/repository/public</url>
</pluginRepository>
</pluginRepositories>
</profile>
</profiles>
<activeProfiles>
<activeProfile>default-repos</activeProfile>
</activeProfiles>
</settings>7.2 版本锁定
<!-- 父 POM 中统一管理版本 -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>33.4.0-jre</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.17.0</version>
</dependency>
</dependencies>
</dependencyManagement>
<!-- 使用 BOM(Bill of Materials)锁定版本 -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>3.4.1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>Gradle 版本锁定:
// build.gradle.kts
plugins {
id("org.springframework.boot") version "3.4.1"
id("io.spring.dependency-management") version "1.1.7"
}
// 使用 Version Catalog(Gradle 7+)
// gradle/libs.versions.toml
[versions]
guava = "33.4.0-jre"
commons-lang3 = "3.17.0"
[libraries]
guava = { module = "com.google.guava:guava", version.ref = "guava" }
commons-lang3 = { module = "org.apache.commons:commons-lang3", version.ref = "commons-lang3" }7.3 scope 与打包插件提醒
<!-- servlet-api 由运行容器提供,不能打进 WAR -->
<dependency>
<groupId>jakarta.servlet</groupId>
<artifactId>jakarta.servlet-api</artifactId>
<version>6.1.0</version>
<scope>provided</scope>
</dependency>
<!-- 测试依赖只在 test 阶段可见 -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.11.4</version>
<scope>test</scope>
</dependency>dependencyManagement 只负责“锁版本”,不会自动引入依赖;真正要用还得在 <dependencies> 里声明。打 fat jar 时优先用 maven-shade-plugin(能处理依赖重定位和资源合并),只是简单把依赖拷贝到目录时再考虑 maven-assembly-plugin。
7.4 依赖管理清单
# 定期检查依赖更新
mvn versions:display-dependency-updates
mvn versions:display-plugin-updates
# 检查安全漏洞
mvn org.owasp:dependency-check-maven:check
# Gradle
./gradlew dependencyUpdates
./gradlew dependencyCheckAnalyze总结
| 环境 | 方案 |
|---|---|
| 个人开发 | 阿里云镜像,直接复制 settings.xml |
| 企业开发 | 私服(Nexus/Artifactory)+ 阿里云镜像 |
| 信创内网 | 本地 Nexus + 离线仓库同步 |
| CI/CD | 镜像配置写入构建脚本,使用环境变量管理凭证 |
三个核心原则:
- **mirrorOf 不要用 ***:避免覆盖私服地址
- 凭证不要硬编码:使用环境变量或 CI Secret
- 定期更新镜像地址:镜像源地址可能会变化