首页 / 资讯中心 / 文章详情

Maven settings.xml 完整配置手册(含私服、镜像、密码加密、profile 切换)

Maven settings.xml 完整配置手册(含私服、镜像、密码加密、profile 切换) ★ FEATURED ARTICLE
Maven 用了这么多年真正让我停下来认真读一遍 settings.xml 文档的契机是去年公司换了一次 Nexus 私服地址。运维发了个新 settings.xml 让全员替换结果我一拉代码——所有依赖全部 404。排查了半小时发现是新配置里 mirrorOf 写了 *把项目 pom 里声明的第三方仓库也一并劫持到了新私服上而新私服还没同步完。这件事之后我意识到settings.xml 这个文件大部分人只是抄来能用就行但对它的加载顺序、mirror 匹配规则、profile 激活机制其实一知半解。出了问题只能靠删文件重装来修。这篇把 settings.xml 每个配置项讲清楚重点放在镜像匹配规则、密码加密的完整操作流程、多环境 profile 切换这三个最容易出错的地方。所有示例基于 Maven 3.9.x低版本3.6行为一致。文件位置与加载优先级settings.xml 有两份Maven 会合并加载级别路径作用域Global${maven.home}/conf/settings.xml当前机器所有用户User${user.home}/.m2/settings.xml当前用户Windows 上 User 级别就是 C:\Users\你\.m2\settings.xml。加载规则User 级别优先。如果两边都定义了同一个 server 的 idUser 级别覆盖 Global。如果两边都定义了 mirror则两份都会生效不是覆盖关系匹配时按声明顺序。建议日常开发只维护 User 级别的 ~/.m2/settings.xml不要动 Maven 安装目录下的 conf。原因升级 Maven 版本时 conf 会被覆盖你的配置就丢了。用命令确认 Maven 实际读的是哪个文件mvn --version # Maven home: D:\apache-maven-3.9.6 ← conf/settings.xml 在这下面 mvn help:effective-settings # 输出最终合并后的生效配置最准基本结构一份 settings.xml 的骨架长这样?xml version1.0 encodingUTF-8? settings xmlnshttp://maven.apache.org/SETTINGS/1.2.0 xmlns:xsihttp://www.w3.org/2001/XMLSchema-instance xsi:schemaLocationhttp://maven.apache.org/SETTINGS/1.2.0 https://maven.apache.org/xsd/settings-1.2.0.xsd localRepository/ interactiveMode/ offline/ pluginGroups/ servers/ mirrors/ proxies/ profiles/ activeProfiles/ /settings下面逐个讲。localRepository本地仓库路径localRepositoryD:/maven-repo/localRepository默认是 ~/.m2/repository。建议改到非系统盘原因一个中等 Java 项目跑几次 mvn clean install仓库就能到 5~10 GB多项目累积下来 30~50 GB 很正常C 盘满了会导致各种诡异问题IDEA 索引失败、Git 操作报错等路径注意Windows 上用正斜杠 / 或双反斜杠 \\单反斜杠 \ 在 XML 里虽然大部分时候也能识别但不保证所有 Maven 插件都兼容。改完之后验证mvn help:evaluate -Dexpressionsettings.localRepository -q -DforceStdout # 输出D:/maven-repomirrors镜像配置重点基本语法mirrors mirror idaliyun-public/id nameAliyun Maven Mirror/name urlhttps://maven.aliyun.com/repository/public/url mirrorOfcentral/mirrorOf /mirror /mirrors四个字段id唯一标识也是认证时关联 server 的 key如果镜像需要登录name描述随便写url镜像地址mirrorOf匹配规则——决定哪些仓库的请求会被这个镜像拦截mirrorOf 匹配规则核心这是 settings.xml 里最容易出错的地方我见过至少五种写法行为完全不同mirrorOf 值含义使用场景central只代理 Maven Central最安全推荐*代理所有仓库包括 pom 里声明的第三方仓库危险容易劫持私服external:*代理所有非 localhost、非 file:// 的仓库比 * 稍安全repo1,repo2代理 id 为 repo1 或 repo2 的仓库精确控制*,!company-nexus代理所有仓库但排除id 为 company-nexus 的有私服时的推荐写法血泪教训如果你有公司私服mirrorOf 千万不要用 *。否则 pom.xml 里声明的私服仓库请求会被镜像拦截镜像上没有你公司的内部 jar直接 404。正确做法mirror idaliyun-public/id nameAliyun Maven Mirror/name urlhttps://maven.aliyun.com/repository/public/url mirrorOfcentral,!company-nexus/mirrorOf /mirror或者更严格一点只代理 centralmirrorOfcentral/mirrorOf多镜像配置可以配多个 mirrorMaven 按声明顺序匹配第一个命中的生效mirrors !-- 优先走公司内网镜像速度快、有内部包 -- mirror idcompany-mirror/id urlhttps://nexus.company.com/repository/maven-public//url mirrorOfcentral/mirrorOf /mirror !-- 公司镜像挂了或在外网时的备选 -- mirror idaliyun-public/id urlhttps://maven.aliyun.com/repository/public/url mirrorOfcentral/mirrorOf /mirror /mirrors注意同一个 mirrorOf 目标如果声明了多个 mirrorMaven 3.9 的行为是只用第一个匹配的不会 fallback 到第二个这跟 Docker 的 registry-mirrors 不一样。想要 failover 效果需要用 Maven 3.9 的 blocked 配合或者在 CI 里用脚本切换。常用国内镜像地址2026 年 9 月仍可用!-- 阿里云推荐稳定 -- urlhttps://maven.aliyun.com/repository/public/url !-- 华为云 -- urlhttps://repo.huaweicloud.com/repository/maven//url !-- 腾讯云 -- urlhttps://mirrors.cloud.tencent.com/nexus/repository/maven-public//url阿里云还有个 Spring 专用仓库拉 Spring 的 snapshot 版时需要单独配mirror idaliyun-spring/id urlhttps://maven.aliyun.com/repository/spring/url mirrorOfspring-milestones,spring-snapshots/mirrorOf /mirrorservers认证配置含密码加密基本用法当你要往私服 deploy jar或者访问需要登录的仓库时需要配认证servers server idcompany-nexus/id usernamezhangsan/username passwordMyPssw0rd/password /server /serversid 必须跟 pom.xml 里 distributionManagement 的仓库 id或者 settings.xml 里 mirror / repository 的 id完全一致区分大小写。不一致的话认证不生效报 401 Unauthorized。明文密码的问题上面那种写法密码是明文存在 ~/.m2/settings.xml 里的。问题你 dotfiles 如果同步到 GitHub密码就泄露了团队共用一台构建机时所有人都能看到你的密码安全审计过不了密码加密完整流程Maven 提供了两层加密master password加密server password。第一步创建 master passwordmvn --encrypt-master-password YourMasterPss123输出类似{Qe3kF5bJ7mN2pR8sT1uV4wX6yZ0aB3cD5eF7gH9iJ0}把这个输出写到 ~/.m2/settings-security.xml没有就新建settingsSecurity master{Qe3kF5bJ7mN2pR8sT1uV4wX6yZ0aB3cD5eF7gH9iJ0}/master /settingsSecurity第二步用 master password 加密 server passwordmvn --encrypt-password MyPssw0rd输出类似{aB1cD2eF3gH4iJ5kL6mN7oP8qR9sT0uV1wX2yZ3aB4c}第三步把加密后的密码写到 settings.xmlserver idcompany-nexus/id usernamezhangsan/username password{aB1cD2eF3gH4iJ5kL6mN7oP8qR9sT0uV1wX2yZ3aB4c}/password /server验证mvn deploy -DaltDeploymentRepositorycompany-nexus::default::https://nexus.company.com/repository/maven-releases/不报 401 就说明认证通过了。注意事项settings-security.xml 的权限建议设为只有当前用户可读Linux/Macchmod 600 ~/.m2/settings-security.xmlmaster password 忘了的话删掉 settings-security.xml 重来就行它不影响已经加密的密码只要你不改 master如果改了 master password之前所有 --encrypt-password 生成的密文都要重新生成CI 环境Jenkins/GitLab CI通常用环境变量注入而不是 settings-security.xml后面 profile 那节会讲proxies代理配置公司内网需要走 HTTP 代理才能出外网时配这个proxies proxy idcompany-proxy/id activetrue/active protocolhttp/protocol hostproxy.company.com/host port8080/port usernamezhangsan/username password{加密后的密码}/password nonProxyHosts*.company.com|localhost|127.0.0.1|192.168.*/nonProxyHosts /proxy /proxiesnonProxyHosts 用 | 分隔支持 * 通配。公司内网的私服地址一定要加进去否则访问私服也走代理绕一圈不说还可能鉴权失败。大部分开发者不需要配这个——只有你的机器不能直连外网、必须通过代理服务器出网时才用。如果配了代理但拉包还是超时先确认 nonProxyHosts 是不是漏了私服域名。profiles activeProfiles多环境切换为什么需要 profile典型场景公司内网用 Nexus 私服在家用阿里云公共镜像开发环境用 snapshot 仓库实时更新发布环境只走 release 仓库不同项目用不同的 JDK 版本或编译参数CI 和本地用不同的仓库配置基本结构profiles profile idcompany/id activation !-- 激活条件 -- /activation repositories !-- 依赖仓库 -- /repositories pluginRepositories !-- 插件仓库 -- /pluginRepositories properties !-- 自定义属性 -- /properties /profile /profiles activeProfiles activeProfilecompany/activeProfile /activeProfiles实战示例公司内网 外网两套配置profiles !-- 公司内网环境 -- profile idoffice/id repositories repository idcompany-nexus/id urlhttps://nexus.company.com/repository/maven-public//url releasesenabledtrue/enabled/releases snapshotsenabledtrue/enabledupdatePolicyalways/updatePolicy/snapshots /repository /repositories pluginRepositories pluginRepository idcompany-nexus/id urlhttps://nexus.company.com/repository/maven-public//url /pluginRepository /pluginRepositories /profile !-- 外网/家庭环境 -- profile idhome/id repositories repository idaliyun/id urlhttps://maven.aliyun.com/repository/public/url releasesenabledtrue/enabled/releases snapshotsenabledfalse/enabled/snapshots /repository /repositories /profile /profiles !-- 默认激活公司环境 -- activeProfiles activeProfileoffice/activeProfile /activeProfiles切换方式方式一改 activeProfiles 里的值永久切换方式二命令行临时指定# 临时用 home profile 构建 mvn clean package -P home # 临时禁用 office profile mvn clean package -P !office方式三用激活条件自动切换后面讲自动激活基于文件或环境变量profile idci/id activation !-- 当环境变量 CItrue 时自动激活 -- property nameenv.CI/name valuetrue/value /property /activation properties maven.test.skiptrue/maven.test.skip /properties /profileprofile idjdk17/id activation !-- 当 JDK 版本为 17 时自动激活 -- jdk17/jdk /activation properties maven.compiler.release17/maven.compiler.release /properties /profileprofile idhas-settings-file/id activation !-- 当某个文件存在时自动激活 -- file exists${user.home}/.company-vpn-active/exists /file /activation !-- 只有连了 VPN创建了标记文件才走内网仓库 -- /profile最后这个 file 激活的玩法挺实用连上 VPN 后 touch ~/.company-vpn-active断开后 rm ~/.company-vpn-activeMaven 自动切换仓库源不用手动改 settings.xml。用 properties 统一版本号profile 里可以定义 properties然后在 pom.xml 里用 ${xxx} 引用profile iddev/id properties deploy.envdev/deploy.env spring.profiles.activedev/spring.profiles.active /properties /profile profile idprod/id properties deploy.envprod/deploy.env spring.profiles.activeprod/spring.profiles.active /properties /profile配合 maven-resources-plugin 的 filtering 功能可以在打包时把 application.yml 里的占位符替换成对应环境的值。不过现在 Spring Boot 项目更推荐用 spring.profiles.active 运行时切换而不是编译期替换——编译期替换意味着每个环境要单独打一次包容易出错。完整示例我目前在用的 settings.xml下面是一份整合了上面所有内容的完整文件改改 URL 和账号就能直接用?xml version1.0 encodingUTF-8? settings xmlnshttp://maven.apache.org/SETTINGS/1.2.0 xmlns:xsihttp://www.w3.org/2001/XMLSchema-instance xsi:schemaLocationhttp://maven.apache.org/SETTINGS/1.2.0 https://maven.apache.org/xsd/settings-1.2.0.xsd !-- 本地仓库 -- localRepositoryD:/maven-repo/localRepository !-- 镜像只代理 central排除私服 -- mirrors mirror idaliyun-public/id nameAliyun Maven Public/name urlhttps://maven.aliyun.com/repository/public/url mirrorOfcentral,!company-nexus/mirrorOf /mirror /mirrors !-- 认证 -- servers server idcompany-nexus/id usernamezhangsan/username password{aB1cD2eF3gH4iJ5kL6mN7oP8qR9sT0uV1wX2yZ3aB4c}/password /server !-- deploy 用的认证id 必须和 pom 的 distributionManagement 一致 -- server idnexus-releases/id usernamezhangsan/username password{aB1cD2eF3gH4iJ5kL6mN7oP8qR9sT0uV1wX2yZ3aB4c}/password /server server idnexus-snapshots/id usernamezhangsan/username password{aB1cD2eF3gH4iJ5kL6mN7oP8qR9sT0uV1wX2yZ3aB4c}/password /server /servers !-- Profile公司环境 -- profiles profile idcompany/id repositories repository idcompany-nexus/id urlhttps://nexus.company.com/repository/maven-public//url releasesenabledtrue/enabled/releases snapshots enabledtrue/enabled updatePolicyinterval:5/updatePolicy /snapshots /repository /repositories pluginRepositories pluginRepository idcompany-nexus/id urlhttps://nexus.company.com/repository/maven-public//url /pluginRepository /pluginRepositories /profile /profiles activeProfiles activeProfilecompany/activeProfile /activeProfiles /settingsupdatePolicyinterval:5/updatePolicy 表示 snapshot 版本每 5 分钟检查一次更新不会每次构建都去拉。开发阶段频繁改 snapshot 时可以改成 always稳定后改成 daily。常见问题排查拉包报 404 Not Found先确认这个包在 Maven Central 上存不存在去 https://search.maven.org 搜。如果 Central 上没有、只在公司私服上有那多半是 mirrorOf* 把私服请求劫持到了公共镜像。改成 mirrorOfcentral,!私服id。拉包报 401 Unauthorizedserver 的 id 和仓库的 id 不匹配。用 mvn help:effective-settings 看最终生效的 server 列表再跟 mvn dependency:resolve -X 输出的仓库 id 对比。snapshot 版本拉不到最新Maven 默认对 snapshot 的更新策略是 daily——一天只检查一次。强制刷新mvn clean package -U-U 参数强制更新所有 snapshot 依赖。IDEA 和命令行行为不一致IDEA 可能用了自己 bundled 的 Maven 和另一份 settings.xml。检查Settings → Build Tools → Maven → Maven home path 和 User settings file确保跟命令行用的是同一套。mvn deploy 报 400 Bad Request往 release 仓库重复 deploy 同一个版本号会被拒绝Nexus 默认策略。要么升版本号要么在 Nexus 上把对应仓库的 Deployment Policy 改成 Allow redeploy不推荐release 版本应该不可变。下载速度慢跑 mvn dependency:resolve -X看日志里实际请求的 URL 是不是你配的镜像地址。如果不是说明 mirror 没生效——检查 mirrorOf 是否匹配了目标仓库的 id。仓库路径含 _remote.repositories 文件导致本地 jar 不生效本地仓库每个目录下有个 _remote.repositories 文件记录了 jar 是从哪个远程仓库下载的。如果你手动把 jar 复制到本地仓库Maven 可能因为它不认这个来源而忽略它。解法删掉那个目录下的 _remote.repositories或者用 mvn install:install-file 正规安装mvn install:install-file \ -Dfilepath/to/your.jar \ -DgroupIdcom.example \ -DartifactIdyour-lib \ -Dversion1.0.0 \ -Dpackagingjar小结settings.xml 配置的核心逻辑就三件事从哪里拉包mirrors repositories、用什么身份拉servers 加密、什么条件下走哪套配置profiles activation。日常开发建议只维护一份 User 级别的 ~/.m2/settings.xml用 profile 做环境切换而不是维护多份文件。密码一定要加密settings-security.xml 不要提交到版本控制。如果你现在的 settings.xml 是从别人那里抄来的花十分钟跑一下 mvn help:effective-settings看看实际生效的配置是不是你以为的那样——很多时候问题就出在以为配了但其实没生效。
阅读完成 · 觉得有帮助?
咨询建站