必须同时满足资源过滤开启、占位符写法匹配、profile激活成功三个条件,否则打包后仍为${db.url}原样;最常见原因是profile未真正激活或被settings.xml中同名profile静默覆盖。

能实现,但必须同时满足三个条件:资源过滤开启、占位符写法匹配、Profile 激活成功;缺一不可,否则打包后仍是 ${db.url} 原样字符串。
为什么 mvn package -Pprod 打包后配置还是 dev 的?
最常见原因是 Profile 没真正激活,或者被覆盖。不是语法错,而是优先级问题:
-
settings.xml里有同名<profile></profile>且activeByDefault=true,会静默覆盖项目pom.xml中的定义 -
pom.xml中多个<id>dev</id>写重复了,后声明的 profile 会覆盖前面的 - IDE(如 IntelliJ)的 Maven Run Configuration 没传
-Pprod,实际执行的是无参数的mvn clean package - 用
mvn help:active-profiles可验证当前生效的 profile 列表
如何让 application.properties 中的 ${xxx} 被正确替换?
关键在 <filtering>true</filtering> 和路径声明是否匹配:
- 必须在
<build><resources></resources></build>下显式声明src/main/resources并设filtering=true - 不能只靠 Spring Boot 的
spring.profiles.active=prod—— 那是运行时行为,不影响 Maven 打包阶段的变量替换 - 如果资源目录下还有子文件夹(如
config/),需额外加<resource></resource>块并指定<directory></directory> - 示例片段:
<build><resources><resource><directory>src/main/resources</directory><filtering>true</filtering></resource></resources></build>
怎么避免 Maven 和 Spring Boot 同时解析 ${} 导致占位符失效?
两者都默认解析 ${xxx},冲突后要么报 Could not resolve placeholder,要么值为空。唯一稳妥解法是错开解析符号:
- 在
pom.xml的<build></build>中改用@xxx@格式:<properties><delimiters><delimiter>@</delimiter></delimiters></properties>
- 对应地,把
application.properties中的${db.url}改成@db.url@ - Spring Boot 默认不处理
@xxx@,彻底规避双重解析 - 别用
$${xxx}—— Maven 3.5+ 已弃用,且在某些插件版本中不可靠
Profile 定义放在 pom.xml 还是 settings.xml?
取决于配置性质:
- 环境相关的构建参数(如数据库地址、API 域名)应定义在项目级
pom.xml的<profiles></profiles>中,保证可复现、可提交、CI 可控 - 仅与本地机器有关的设置(如私有仓库认证、镜像地址)才放用户级
~/.m2/settings.xml,避免泄露敏感信息 - 全局
Maven/conf/settings.xml不建议放业务环境配置,容易被团队成员误覆盖或忽略 - 一个项目里混用两种来源的 profile 时,
settings.xml中的<properties></properties>会覆盖pom.xml中同名项,务必检查
最容易被忽略的点是:Profile 本身不修改任何文件内容,它只是开关;真正干活的是资源过滤阶段对 @xxx@ 或 ${xxx} 的文本替换。只要没看到 target/classes/application.properties 里对应值被替换成真实地址,就说明链条断在了某一处——先查 mvn help:active-profiles,再看 target/classes 下的最终文件内容,比猜快得多。











