SpringBoot Profiles多环境管理

SpringBoot Profiles多环境管理

Spring Boot 简化了配置,但日志管理依然需要重视。日志配置、链路追踪、排查思路都是日常开发中会遇到的问题。本文讲实际项目中的日志管理经验。

Profile 配置方式

#

1. 配置文件命名

src/main/resources/
├── application.yml # 公共配置
├── application-dev.yml # 开发环境
├── application-test.yml # 测试环境
└── application-prod.yml # 生产环境

#

2. 激活 Profile

# application.yml
spring:
profiles:
active: dev
# 启动参数
java -jar app.jar --spring.profiles.active=prod

# 环境变量
export SPRING_PROFILES_ACTIVE=prod

#

3. Profile 组(Spring Boot 2.4+)

spring:
profiles:
group:
local:
- dev
- local-db
- local-cache
production:
- prod
- prod-db
- prod-cache
- monitoring
java -jar app.jar --spring.profiles.active=production
# 相当于激活:prod, prod-db, prod-cache, monitoring

@Profile 注解

#

Bean 级别

@Configuration
public class DataSourceConfig {

@Bean
@Profile("dev")
public DataSource devDataSource() {
return DataSourceBuilder.create()
.url("jdbc:h2:mem:testdb")
.build();
}

@Bean
@Profile("prod")
public DataSource prodDataSource() {
return DataSourceBuilder.create()
.url("jdbc:mysql://prod:3306/db")
.build();
}

@Bean
@Profile("!prod") // 非 prod 环境
public MockService mockService() {
return new MockService();
}
}

#

配置类级别

@Profile("dev")
@Configuration
public class DevConfig {
@PostConstruct
public void init() {
System.out.println("开发环境配置加载");
}
}

@Profile("prod")
@Configuration
public class ProdConfig {
@Bean
public SecurityConfig securityConfig() {
return new SecurityConfig();
}
}

#

多 Profile

@Profile({"dev", "test"})
@Component
public class DebugInterceptor implements HandlerInterceptor {
// 只在 dev/test 环境生效
}

Profile 条件化配置

#

@ConditionalOnProperty

@Component
@ConditionalOnProperty(prefix = "feature", name = "new-ui", havingValue = "true")
public class NewUIService {
// 当 feature.new-ui=true 时生效
}

@Component
@ConditionalOnProperty(prefix = "feature", name = "new-ui", matchIfMissing = true)
public class DefaultUIService {
// 当 feature.new-ui 未配置时也生效
}

#

配置属性

# application-dev.yml
feature:
new-ui: true
cache: false

# application-prod.yml
feature:
new-ui: false
cache: true

环境特定配置

#

开发环境

# application-dev.yml
spring:
datasource:
url: jdbc:h2:mem:testdb
driver-class-name: org.h2.Driver

jpa:
hibernate:
ddl-auto: create-drop
show-sql: true

logging:
level:
com.example: DEBUG
org.hibernate.SQL: DEBUG

#

测试环境

# application-test.yml
spring:
datasource:
url: jdbc:mysql://test-db:3306/test_db
username: test
password: test

redis:
host: test-redis

server:
port: 8081

#

生产环境

# application-prod.yml
spring:
datasource:
url: jdbc:mysql://prod-db:3306/prod_db
username: ${DB_USERNAME}
password: ${DB_PASSWORD}
hikari:
maximum-pool-size: 50
minimum-idle: 10

jpa:
hibernate:
ddl-auto: none
show-sql: false

logging:
level:
root: WARN
com.example: INFO

获取当前 Profile

@Component
public class ProfileChecker implements EnvironmentAware {

private Environment environment;

@Override
public void setEnvironment(Environment environment) {
this.environment = environment;
}

public void checkProfile() {
// 判断是否在指定 profile
boolean isDev = environment.acceptsProfiles(Profiles.of("dev"));

// 获取所有 active profiles
String[] activeProfiles = environment.getActiveProfiles();

// 判断是否在任一 profile
boolean isProdOrTest = environment.acceptsProfiles(Profiles.of("prod", "test"));

System.out.println("当前环境: " + String.join(", ", activeProfiles));
}
}

Profile 与配置优先级

优先级从高到低:

1. 命令行参数: --server.port=9000
2. Java 系统属性: -Dserver.port=9000
3. 环境变量: SERVER_PORT=9000
4. application-{profile}.properties/yml
5. application.properties/yml
6. @PropertySource
7. SpringApplication.setDefaultProperties

配置加密

# application.yml
jasypt:
encryptor:
password: ${JASYPT_PASSWORD}

spring:
datasource:
password: ENC(encrypted_value_here)
@Configuration
public class JasyptConfig {

@Bean("jasyptStringEncryptor")
public StringEncryptor stringEncryptor() {
PooledPBEStringEncryptor encryptor = new PooledPBEStringEncryptor();
SimpleStringPBEConfig config = new SimpleStringPBEConfig();
config.setPassword(System.getenv("JASYPT_PASSWORD"));
config.setAlgorithm("PBEWITHHMACSHA512ANDAES_256");
config.setPoolSize(1);
encryptor.setConfig(config);
return encryptor;
}
}

测试中使用 Profile

@SpringBootTest
@ActiveProfiles("test")
class MyIntegrationTest {
// 使用 application-test.yml 配置
}

@SpringBootTest
@ActiveProfiles({"test", "no-security"})
class MyControllerTest {
// 使用多个 profile
}

容器化部署

#

Dockerfile

FROM openjdk:17-jdk-slim
COPY target/app.jar app.jar
ENTRYPOINT ["java", "-Dspring.profiles.active=${PROFILE}", "-jar", "/app.jar"]

#

Docker Compose

version: '3'
services:
app:
image: myapp:latest
environment:
- SPRING_PROFILES_ACTIVE=prod
- DB_USERNAME=root
- DB_PASSWORD=secret

#

Kubernetes

apiVersion: apps/v1
kind: Deployment
spec:
template:
spec:
containers:
- name: app
image: myapp:latest
env:
- name: SPRING_PROFILES_ACTIVE
value: "prod"
- name: DB_USERNAME
valueFrom:
secretKeyRef:
name: db-secret
key: username

最佳实践

实践 说明
默认配置 application.yml 放公共配置
环境配置 application-{env}.yml 放环境差异
敏感信息 使用环境变量或配置中心
本地开发 使用 H2 / 内存中间件
生产环境 关闭调试日志,启用监控
配置验证 启动时验证必要配置是否存在

总结

Spring Profiles 提供了灵活的环境管理能力:

  1. 配置文件分离:application-{profile}.yml
  2. 条件化 Bean:@Profile 注解
  3. Profile 组:组合多个 profile
  4. 优先级:命令行 > 环境变量 > profile 配置 > 默认配置

合理使用 Profile,可以让应用在不同环境间无缝切换。

核心要点

  1. 日志级别设置:根据环境设置合适的级别

  2. 日志格式配置:添加 traceId 便于链路追踪

  3. 日志输出:控制台输出和文件输出的配置

  4. 日志归档:设置滚动策略和保留时间

总结

日志是排查问题的生命线,合理配置日志可以提升排查效率。在实际项目中,结合 ELK 等工具搭建日志系统,可以更好地管理和分析日志。


   转载规则


《SpringBoot Profiles多环境管理》 小乐 采用 知识共享署名 4.0 国际许可协议 进行许可。
  目录