在使用 Maven 进行构建时,你可能遇到这样的问题:
项目中的
pom.xml
明明已经配置了自定义,但最终下载依赖时却没有走项目配置的地址,而是走了你本地
settings.xml
中配置的 mirror。为什么?
这其实是 Maven 的一个机制性行为,也是很多人第一次接触 Maven 私服时容易踩的坑。
你在项目的 pom.xml
中配置了如下 repository:
<repositories>
<repository>
<id>internal-snapshotsid>
<url>https://repo.mycompany.com/snapshotsurl>
repository>
repositories>
同时你本地的 ~/.m2/settings.xml
中配置了一个镜像:
<mirrors>
<mirror>
<id>nexusid>
<mirrorOf>*mirrorOf>
<url>https://mirror.mycompany.com/repository/maven-publicurl>
mirror>
mirrors>
结果构建时 Maven 总是走 mirror.mycompany.com
,项目配置的 snapshot 仓库完全不生效。
Maven 的官方文档说明如下:
When a
is configured for a repository, it replaces all requests that match the
rule.
Even if the project explicitly declares a, 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>nexusid>
<mirrorOf>centralmirrorOf>
<url>https://mirror.mycompany.com/repository/maven-centralurl>
mirror>
这样,Maven 只会用 mirror 替换默认的 Maven Central 仓库,而不会影响你在 pom.xml 中显式声明的 internal-snapshots
仓库。
举个例子,你的 mirror 仍然使用 mirrorOf=*
:
<mirrorOf>*mirrorOf>
这时你可以在项目 pom 中这么做:
<repositories>
<repository>
<id>repo-not-mirroredid>
<url>https://somewhere.com/repourl>
repository>
repositories>
然后,在 mirror 中排除它:
<mirrorOf>*,!repo-not-mirroredmirrorOf>
这样,除了 repo-not-mirrored
,其他仓库请求都被镜像。
settings.xml
在企业构建环境中,如果你希望项目走它自己的配置而非团队统一配置,你可以:
mvn clean install --settings custom-settings.xml
这个 custom-settings.xml
可以:
;mirrorOf=central
)。这样可以保证构建使用的是项目中声明的 repository,而不是本地统一的镜像规则。
执行:
mvn dependency:resolve -X
可以看到每个依赖最终是从哪个仓库下载的,是否被镜像替换,日志中会明确输出。
Maven 的镜像机制设计初衷是方便集中管理依赖源,提升构建速度、缓存命中率、控制源安全。但这也导致了项目自定义 repository 在默认配置下容易被忽视。
只要你记住这条规则:
*Mirror 优先级高于 Repository,且 mirrorOf= 是“全局劫持”。**
就能灵活控制 Maven 的下载行为,避免项目构建时走错仓库、下载失败等问题。