Maven 资源过滤怎么管理多环境配置?
Maven 资源过滤是在构建时把资源文件里的占位符替换成真实值,例如把 ${env}、${jdbc.url} 写进配置文件,再由 Maven 根据 profile 或属性替换。它适合处理少量构建期差异,比如应用名、版本号、环境标识、默认地址。它不适合管理密码、密钥和频繁变化的运行时配置,因为这些内容一旦打进包里,修改就要重新构建。
基本配置
在 POM 里开启过滤时,最好只针对明确的文本文件:
xml<build> <resources> <resource> <directory>src/main/resources</directory> <filtering>true</filtering> <includes> <include>**/*.properties</include> <include>**/*.yml</include> </includes> </resource> <resource> <directory>src/main/resources</directory> <filtering>false</filtering> <excludes> <exclude>**/*.properties</exclude> <exclude>**/*.yml</exclude> </excludes> </resource> </resources> </build>
资源文件中可以这样写:
propertiesapp.name=${project.artifactId} app.version=${project.version} app.env=${deploy.env}
多环境值可以放在 profile 里:
xml<profiles> <profile> <id>prod</id> <properties> <deploy.env>prod</deploy.env> <api.baseUrl>https://api.example.com</api.baseUrl> </properties> </profile> </profiles>
构建时指定环境:
bashmvn clean package -Pprod
追问
Maven 资源过滤和 Spring Profile 有什么区别?
Maven 资源过滤发生在构建期,打包后内容已经被替换。Spring Profile 发生在运行期,同一个包可以通过启动参数切换环境。取舍上,如果配置跟构建产物强相关,例如版本号、构建时间,可以用 Maven;如果配置跟部署环境相关,例如数据库地址、开关状态,更适合运行期 Profile 或配置中心。把所有环境都打成不同包会增加发布复杂度,也容易出现“测试包和生产包不是同一个产物”的问题。
为什么不建议过滤整个 resources 目录?
因为 resources 里不一定全是文本文件。图片、字体、证书、Excel 模板等二进制文件如果被过滤,可能会被改坏,错误还不一定在构建阶段暴露。更稳妥的方式是只 include properties、yml、xml 这类确实需要替换的文件。边界是 XML 里如果包含 ${} 但不是 Maven 变量,也要小心误替换。
占位符和业务框架的 ${} 冲突怎么办?
这是资源过滤最常见的坑。Spring、Logback、Shell 模板里也大量使用 ${},Maven 过滤可能提前把它们处理掉。可以改用自定义分隔符,或者只对少数配置文件开启过滤。示例做法是在 resources 插件中配置 delimiter,让 Maven 只替换 @name@ 形式的变量。
xml<plugin> <artifactId>maven-resources-plugin</artifactId> <version>3.3.1</version> <configuration> <delimiters> <delimiter>@</delimiter> </delimiters> <useDefaultDelimiters>false</useDefaultDelimiters> </configuration> </plugin>
密码和 Token 能不能放进过滤文件?
不建议。资源过滤会把值写进最终 jar、war 或镜像里,任何能拿到产物的人都可能反编译或解压看到配置。密码、Token、证书路径这类敏感信息应该来自环境变量、密钥服务、Kubernetes Secret 或配置中心。Maven 可以写默认占位符,但不要把真实密钥放进 POM、filter 文件或 Git 仓库。
多环境配置应该打多个包还是一个包多环境运行?
如果是传统部署,多个 profile 打多个包看起来简单,但会增加制品数量,也让“哪个包上线了”变得难追踪。现代 CI/CD 更推荐一次构建生成一个不可变制品,部署时通过环境变量或配置中心注入差异。Maven 资源过滤适合补充构建元信息,不适合作为完整环境管理系统。除非你的发布流程明确要求按环境出包,否则一个包多环境运行更稳。
资源过滤很好用,但它解决的是构建期替换,不是配置治理。把它用在版本号、环境名、少量默认地址上,会让包更清晰;把它用来塞满所有环境变量和密钥,后面维护成本会很高。