Maven项目中, mirror 与 repository 的优先级
在使用 Maven 进行构建时,你可能遇到这样的问题:
项目中的
pom.xml
明明已经配置了自定义<repository>
,但最终下载依赖时却没有走项目配置的地址,而是走了你本地settings.xml
中配置的 mirror。为什么?
这其实是 Maven 的一个机制性行为,也是很多人第一次接触 Maven 私服时容易踩的坑。
一、问题复现
你在项目的 pom.xml
中配置了如下 repository:
<repositories>
<repository>
<id>internal-snapshots</id>
<url>https://repo.mycompany.com/snapshots</url>
</repository>
</repositories>
同时你本地的 ~/.m2/settings.xml
中配置了一个镜像:
<mirrors>
<mirror>
<id>nexus</id>
<mirrorOf>*</mirrorOf>
<url>https://mirror.mycompany.com/repository/maven-public</url>
</mirror>
</mirrors>
结果构建时 Maven 总是走 mirror.mycompany.com
,项目配置的 snapshot 仓库完全不生效。
二、背后的机制:Mirror 的强制性重定向
Maven 的官方文档说明如下:
When a
<mirror>
is configured for a repository, it replaces all requests that match the<mirrorOf>
rule.
Even if the project explicitly declares a<repository>
, it will be ignored if its id is matched by the mirrorOf pattern.
简单说就是:
mirror 会劫持符合条件的 repository,无论你是否在 pom 中手动配置了仓库。
最典型的例子:
<mirrorOf>*</mirrorOf>
这意味着:匹配所有的 repository,包括你项目里自定义的 snapshot、release 仓库!
三、解决方案
方案一:修改 mirrorOf
匹配范围,避免“全局劫持”
你可以将 *
改为更精确的仓库 id,比如:
<mirror>
<id>nexus</id>
<mirrorOf>central</mirrorOf>
<url>https://mirror.mycompany.com/repository/maven-central</url>
</mirror>
这样,Maven 只会用 mirror 替换默认的 Maven Central 仓库,而不会影响你在 pom.xml 中显式声明的 internal-snapshots
仓库。
方案二:为项目 repository 设置一个不会被镜像命中的 id
举个例子,你的 mirror 仍然使用 mirrorOf=*
:
<mirrorOf>*</mirrorOf>
这时你可以在项目 pom 中这么做:
<repositories>
<repository>
<id>repo-not-mirrored</id> <!-- 起一个 mirrorOf 不匹配的名字 -->
<url>https://somewhere.com/repo</url>
</repository>
</repositories>
然后,在 mirror 中排除它:
<mirrorOf>*,!repo-not-mirrored</mirrorOf>
这样,除了 repo-not-mirrored
,其他仓库请求都被镜像。
方案三:在 CI/CD 使用特定的 settings.xml
在企业构建环境中,如果你希望项目走它自己的配置而非团队统一配置,你可以:
mvn clean install --settings custom-settings.xml
这个 custom-settings.xml
可以:
- 不配置
<mirrors>
; - 或者只镜像一部分仓库(比如
mirrorOf=central
)。
这样可以保证构建使用的是项目中声明的 repository,而不是本地统一的镜像规则。
四、检查是否生效的方法
执行:
mvn dependency:resolve -X
可以看到每个依赖最终是从哪个仓库下载的,是否被镜像替换,日志中会明确输出。
五、结语
Maven 的镜像机制设计初衷是方便集中管理依赖源,提升构建速度、缓存命中率、控制源安全。但这也导致了项目自定义 repository 在默认配置下容易被忽视。
只要你记住这条规则:
*Mirror 优先级高于 Repository,且 mirrorOf= 是“全局劫持”。**
就能灵活控制 Maven 的下载行为,避免项目构建时走错仓库、下载失败等问题。