Maven Profile 多环境配置:如何实现一套代码适配 dev/test/prod?(附完整配置)
【摘要】 开发时改配置、测试时改配置、上线时还要改配置——有没有一种方法能让代码在不同环境自动适配?本文介绍 Maven Profile 的用法,从基础的 pom.xml 配置到生产环境的敏感信息管理,手把手教你实现一套代码多环境运行。
Maven Profile 多环境配置:如何实现一套代码适配 dev/test/prod?(附完整配置)
⏱️ 阅读预估时间: 12 分钟
摘要: 开发时改配置、测试时改配置、上线时还要改配置——有没有一种方法能让代码在不同环境自动适配?本文介绍 Maven Profile 的用法,从基础的 pom.xml 配置到生产环境的敏感信息管理,手把手教你实现一套代码多环境运行。
🎯 前言:多环境管理的痛点
1.1 那些年被环境配置坑过的经历
场景一:手动改配置上线
开发:代码写完了,准备上线
运维:好的,我先改下数据库配置
再改 Redis 地址
还有消息队列...
哎呀,改错了一个参数!
结果:上线失败,回滚...
场景二:配置文件满天飞
config-dev.properties
config-test.properties
config-prod.properties
config-backup.properties
config-old.properties
...
哪个才是真正在用的?
场景三:环境混淆
开发 A: 我本地好好的啊
开发 B:你用的是哪个环境?
开发 A:好像是 test 环境?
开发 B:不对,这是 prod 的配置!
完了,生产数据被污染了...
1.2 为什么需要 Profile?
🌟 第一章:Profile 基础入门
2.1 什么是 Profile?
Profile 定义:
Profile 是 Maven 的一组配置集合,可以根据不同条件激活
核心作用:
- 同一套代码,不同环境运行
- 动态切换配置,无需修改代码
- 标准化环境管理
适用场景:
✅ 开发环境 (development)
✅ 测试环境 (testing)
✅ 预发布环境 (staging)
✅ 生产环境 (production)
2.2 Profile 的三种类型
<!-- 类型 1: pom.xml 中的 Profile -->
<project>
<profiles>
<profile>
<id>dev</id>
<!-- 配置内容 -->
</profile>
</profiles>
</project>
<!-- 类型 2: settings.xml 中的 Profile -->
<settings>
<profiles>
<profile>
<id>global-config</id>
<!-- 全局配置 -->
</profile>
</profiles>
</settings>
<!-- 类型 3: 独立的 profile.xml(较少用) -->
💡 第二章:数据库配置分离实战
3.1 项目结构
my-project/
├── src/
│ ├── main/
│ │ ├── java/
│ │ └── resources/
│ │ ├── application.yml # 主配置文件
│ │ ├── application-dev.yml # 开发环境
│ │ ├── application-test.yml # 测试环境
│ │ └── application-prod.yml # 生产环境
│ └── test/
├── pom.xml
└── scripts/
└── deploy.sh
3.2 pom.xml 配置
<project>
<profiles>
<!-- 开发环境 -->
<profile>
<id>dev</id>
<properties>
<!-- 环境标识 -->
<env.profile>dev</env.profile>
<!-- 数据库配置 -->
<db.url>jdbc:mysql://localhost:3306/dev_db?useSSL=false</db.url>
<db.username>dev_user</db.username>
<db.password>dev_password</db.password>
<db.driver-class-name>com.mysql.cj.jdbc.Driver</db.driver-class-name>
<!-- Redis 配置 -->
<redis.host>localhost</redis.host>
<redis.port>6379</redis.port>
<redis.password></redis.password>
<!-- 日志级别 -->
<log.level>DEBUG</log.level>
<log.pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n</log.pattern>
</properties>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
</profile>
<!-- 测试环境 -->
<profile>
<id>test</id>
<properties>
<env.profile>test</env.profile>
<db.url>jdbc:mysql://test-db-server:3306/test_db?useSSL=false</db.url>
<db.username>test_user</db.username>
<db.password>test_password</db.password>
<db.driver-class-name>com.mysql.cj.jdbc.Driver</db.driver-class-name>
<redis.host>test-redis-server</redis.host>
<redis.port>6379</redis.port>
<redis.password>redis_password</redis.password>
<log.level>INFO</log.level>
<log.pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n</log.pattern>
</properties>
</profile>
<!-- 生产环境 -->
<profile>
<id>prod</id>
<properties>
<env.profile>prod</env.profile>
<db.url>jdbc:mysql://prod-db-master:3306/prod_db?useSSL=true&requireSSL=true</db.url>
<db.username>${env.PROD_DB_USERNAME}</db.username>
<db.password>${env.PROD_DB_PASSWORD}</db.password>
<db.driver-class-name>com.mysql.cj.jdbc.Driver</db.driver-class-name>
<redis.host>prod-redis-cluster</redis.host>
<redis.port>6379</redis.port>
<redis.password>${env.PROD_REDIS_PASSWORD}</redis.password>
<log.level>WARN</log.level>
<log.pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</log.pattern>
</properties>
</profile>
</profiles>
</project>
3.3 Spring Boot 集成
# application.yml
spring:
profiles:
active: @env.profile@
datasource:
url: ${db.url}
username: ${db.username}
password: ${db.password}
driver-class-name: ${db.driver-class-name}
redis:
host: ${redis.host}
port: ${redis.port}
password: ${redis.password}
logging:
level:
root: ${log.level}
pattern:
console: ${log.pattern}
3.4 资源文件过滤
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.yml</include>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering> <!-- 启用变量替换 -->
</resource>
</resources>
</build>
🔐 第三章:敏感信息加密
4.1 环境变量方式(推荐⭐⭐⭐⭐⭐)
<!-- pom.xml -->
<profile>
<id>prod</id>
<properties>
<!-- 从环境变量读取 -->
<db.username>${env.PROD_DB_USERNAME}</db.username>
<db.password>${env.PROD_DB_PASSWORD}</db.password>
<redis.password>${env.PROD_REDIS_PASSWORD}</redis.password>
<jwt.secret>${env.JWT_SECRET}</jwt.secret>
</properties>
</profile>
设置环境变量:
# Linux/Mac
export PROD_DB_USERNAME=prod_admin
export PROD_DB_PASSWORD=SecureP@ssw0rd!
export PROD_REDIS_PASSWORD=RedisP@ss!
export JWT_SECRET=MySuperSecretJWTKey123!
# Windows PowerShell
$env:PROD_DB_USERNAME="prod_admin"
$env:PROD_DB_PASSWORD="SecureP@ssw0rd!"
4.2 Maven 密码加密
# 步骤 1: 生成主密码
mvn --encrypt-master-password
# 输入后得到:{QJ6wvuEfacMHmlqomr3c1IdKJ3DyGxpZgFeoZeXkI8Y=}
# 步骤 2: 创建 security-settings.xml
cat > ~/.m2/security-settings.xml << EOF
<settingsSecurity>
<master>{QJ6wvuEfacMHmlqomr3c1IdKJ3DyGxpZgFeoZeXkI8Y=}</master>
</settingsSecurity>
EOF
chmod 600 ~/.m2/security-settings.xml
# 步骤 3: 加密服务器密码
mvn --encrypt-password
# 输入密码得到:{SmgeP1a3U6iVz7TfQA5QRw==}
# 步骤 4: 在 settings.xml 中使用
<servers>
<server>
<id>prod-db</id>
<username>prod_admin</username>
<password>{SmgeP1a3U6iVz7TfQA5QRw==}</password>
</server>
</servers>
🚀 第四章:一键切换环境
5.1 命令行切换
# 方式 1: 使用-P参数
mvn clean package -Pdev
mvn clean package -Ptest
mvn clean package -Pprod
# 方式 2: 设置默认 Profile
# 在 pom.xml 中设置 activeByDefault
<activation>
<activeByDefault>true</activeByDefault>
</activation>
5.2 自动化部署脚本
#!/bin/bash
# deploy.sh
ENV=${1:-dev} # 默认为 dev 环境
echo "🚀 开始部署到 $ENV 环境..."
# 1. 清理旧的构建
echo "1. 清理旧构建..."
mvn clean
# 2. 根据环境打包
echo "2. 打包应用 ($ENV 环境)..."
mvn package -P$ENV -DskipTests
# 3. 停止旧服务
echo "3. 停止旧服务..."
sudo systemctl stop myapp
# 4. 备份旧版本
echo "4. 备份旧版本..."
sudo cp /opt/myapp/app.jar /opt/myapp/app.jar.backup.$(date +%Y%m%d_%H%M%S)
# 5. 部署新版本
echo "5. 部署新版本..."
sudo cp target/myapp-1.0.0.jar /opt/myapp/app.jar
# 6. 启动服务
echo "6. 启动服务..."
sudo systemctl start myapp
# 7. 检查状态
echo "7. 检查服务状态..."
sleep 5
sudo systemctl status myapp
echo ""
echo "✅ 部署完成!环境:$ENV"
使用方法:
# 部署到开发环境
./deploy.sh dev
# 部署到测试环境
./deploy.sh test
# 部署到生产环境
./deploy.sh prod
5.3 Docker 集成
# Dockerfile
FROM openjdk:17-slim
WORKDIR /app
# 复制 jar 包
COPY target/myapp-*.jar app.jar
# 环境变量(可在运行时覆盖)
ENV ENV_PROFILE=prod
ENV DB_HOST=localhost
ENV DB_PORT=3306
# 启动命令
ENTRYPOINT ["sh", "-c", "java -jar app.jar --spring.profiles.active=${ENV_PROFILE}"]
运行不同环境:
# 开发环境
docker run -e ENV_PROFILE=dev myapp:latest
# 测试环境
docker run -e ENV_PROFILE=test myapp:latest
# 生产环境(带完整配置)
docker run \
-e ENV_PROFILE=prod \
-e DB_HOST=prod-db \
-e DB_PASSWORD=secret \
myapp:latest
🏢 第五章:企业级实战案例
案例一:微服务项目多环境管理
项目背景:
- 20+ 个微服务模块
- 4 套环境(dev/test/staging/prod)
- 每个服务都有独立配置
- 需要统一管理和快速切换
解决方案:
使用 Parent POM + Profile 统一管理
Parent POM 配置:
<!-- parent/pom.xml -->
<project>
<groupId>com.company</groupId>
<artifactId>parent</artifactId>
<version>1.0.0</version>
<packaging>pom</packaging>
<profiles>
<profile>
<id>dev</id>
<properties>
<spring.profiles.active>dev</spring.profiles.active>
<docker.registry>dev-registry.company.com</docker.registry>
<config.server.uri>http://dev-config:8888</config.server.uri>
</properties>
</profile>
<profile>
<id>test</id>
<properties>
<spring.profiles.active>test</spring.profiles.active>
<docker.registry>test-registry.company.com</docker.registry>
<config.server.uri>http://test-config:8888</config.server.uri>
</properties>
</profile>
<profile>
<id>prod</id>
<properties>
<spring.profiles.active>prod</spring.profiles.active>
<docker.registry>prod-registry.company.com</docker.registry>
<config.server.uri>http://prod-config:8888</config.server.uri>
</properties>
</profile>
</profiles>
<build>
<plugins>
<!-- Docker 插件统一配置 -->
<plugin>
<groupId>com.spotify</groupId>
<artifactId>docker-maven-plugin</artifactId>
<configuration>
<registryUrl>${docker.registry}</registryUrl>
<imageName>${docker.registry}/${project.name}:${project.version}</imageName>
</configuration>
</plugin>
</plugins>
</build>
</project>
子模块继承:
<!-- user-service/pom.xml -->
<project>
<parent>
<groupId>com.company</groupId>
<artifactId>parent</artifactId>
<version>1.0.0</version>
</parent>
<!-- 自动继承父 POM 的 Profile -->
</project>
一键构建所有服务:
#!/bin/bash
# build-all.sh
ENV=${1:-dev}
echo "🏗️ 开始构建所有服务 ($ENV 环境)..."
# 构建父 POM
cd parent && mvn clean install -P$ENV
# 构建所有子模块
for module in user-service order-service product-service; do
echo "构建 $module..."
cd $module && mvn clean package -P$ENV -DskipTests
done
echo "✅ 所有服务构建完成!"
案例二:CI/CD流水线集成
# .gitlab-ci.yml
stages:
- build
- test
- deploy
variables:
MAVEN_OPTS: "-XX:MaxMetaspaceSize=512m"
# 构建阶段
build:dev:
stage: build
script:
- mvn clean package -Pdev -DskipTests
only:
- develop
build:test:
stage: build
script:
- mvn clean package -Ptest
only:
- test
build:prod:
stage: build
script:
- mvn clean package -Pprod -DskipTests
only:
- master
# 测试阶段
test:unit:
stage: test
script:
- mvn test -Ptest
only:
- test
test:integration:
stage: test
script:
- mvn verify -Ptest -DskipITs=false
only:
- test
# 部署阶段
deploy:dev:
stage: deploy
script:
- ./deploy.sh dev
only:
- develop
deploy:test:
stage: deploy
script:
- ./deploy.sh test
only:
- test
when: manual # 手动触发
deploy:prod:
stage: deploy
script:
- ./deploy.sh prod
only:
- master
when: manual # 手动触发
environment:
name: production
url: https://www.example.com
📊 第六章:最佳实践总结
7.1 Profile 命名规范
推荐命名:
✅ dev / development - 开发环境
✅ test / testing - 测试环境
✅ staging / pre - 预发布环境
✅ prod / production - 生产环境
✅ local - 本地个人环境
不推荐:
❌ environment1, environment2 (无意义)
❌ my-env, test-env (不规范)
❌ dev1, dev2, dev3 (易混淆)
7.2 配置分离原则
应该分离的配置:
✅ 数据库连接
✅ Redis/MQ 等中间件
✅ 第三方 API 密钥
✅ 日志级别
✅ 功能开关
✅ 缓存策略
不应该分离的配置:
❌ 业务逻辑相关
❌ 核心算法参数
❌ 不变的常量
7.3 安全检查清单
上线前必查:
□ 生产环境没有硬编码密码
□ 使用了环境变量或加密配置
□ 数据库连接使用只读账号(查询服务)
□ 开启了 SSL/TLS
□ 日志级别设置为 WARN 或 ERROR
□ 关闭了 DEBUG 端点
□ 启用了性能监控
□ 配置了告警通知
🎁 福利:完整配置模板
企业级 pom.xml 模板
<?xml version="1.0" encoding="UTF-8"?>
<project>
<modelVersion>4.0.0</modelVersion>
<properties>
<java.version>17</java.version>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<profiles>
<!-- ==================== 开发环境 ==================== -->
<profile>
<id>dev</id>
<properties>
<env.profile>dev</env.profile>
<db.url>jdbc:mysql://localhost:3306/dev_db</db.url>
<db.username>dev</db.username>
<db.password>dev</db.password>
<redis.host>localhost</redis.host>
<log.level>DEBUG</log.level>
</properties>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
</profile>
<!-- ==================== 测试环境 ==================== -->
<profile>
<id>test</id>
<properties>
<env.profile>test</env.profile>
<db.url>jdbc:mysql://test-db:3306/test_db</db.url>
<db.username>test</db.username>
<db.password>test</db.password>
<redis.host>test-redis</redis.host>
<log.level>INFO</log.level>
</properties>
</profile>
<!-- ==================== 生产环境 ==================== -->
<profile>
<id>prod</id>
<properties>
<env.profile>prod</env.profile>
<db.url>jdbc:mysql://prod-db:3306/prod_db</db.url>
<db.username>${env.PROD_DB_USERNAME}</db.username>
<db.password>${env.PROD_DB_PASSWORD}</db.password>
<redis.host>prod-redis</redis.host>
<redis.password>${env.PROD_REDIS_PASSWORD}</redis.password>
<log.level>WARN</log.level>
</properties>
</profile>
</profiles>
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>3.3.0</version>
<configuration>
<delimiters>
<delimiter>@</delimiter>
</delimiters>
<useDefaultDelimiters>false</useDefaultDelimiters>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<profiles>
<profile>@env.profile@</profile>
</profiles>
</configuration>
</plugin>
</plugins>
</build>
</project>
总结
本文介绍了 Maven Profile 的核心用法:
| 场景 | 推荐配置 |
|---|---|
| 开发环境 | mvn package -Pdev,本地调试用 |
| 测试环境 | mvn package -Ptest,CI/CD 自动切换 |
| 生产环境 | mvn package -Pprod,配合环境变量使用 |
关键点:
- 生产环境的密码不要硬编码,用
${env.XXX}读取环境变量 - 善用
activeByDefault设置开发环境为默认 - 多模块项目中在父 POM 统一管理 Profile
🔗 相关文章
上一篇:⚡ Maven 并行构建配置:-T 4C 提速 4 倍的秘密
**下一篇:**🏗️ Maven 多模块项目拆分实战:从单体到微服务的演进之路(即将发布)
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)