# Spring Boot多环境配置实践:Profile策略与配置管理
在企业级应用开发中,不同环境的配置管理是保障应用稳定运行的关键。Spring Boot Profile机制提供了灵活的配置方案,支持开发、测试、预生产和生产等多环境配置管理。
## Profile基础配置架构
Spring Boot支持多种配置源,通过profile-specific配置文件和环境变量实现配置的动态加载。
```yaml
# application.yml - 基础配置
spring:
application:
name: product-service
config:
import:
- optional:file:.env[.properties]
- optional:file:config/application-{profile}.yml
activate:
on-profile: default
# 应用基本信息
app:
version: 1.0.0
description: 商品服务
contact:
email: support@example.com
phone: 400-123-4567
# 日志配置
logging:
level:
root: INFO
com.example: DEBUG
org.springframework.web: INFO
org.hibernate: WARN
pattern:
console: "%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n"
file: "%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n"
file:
name: logs/app.log
max-history: 30
max-size: 10MB
# Actuator监控端点
management:
endpoints:
web:
exposure:
include: health,info,metrics
base-path: /internal
# 默认数据源配置(使用H2内存数据库)
demo:
datasource:
url: jdbc:h2:mem:testdb
driver-class-name: org.h2.Driver
username: sa
password: ""
hikari:
maximum-pool-size: 5
connection-timeout: 30000
jpa:
hibernate:
ddl-auto: create-drop
show-sql: true
properties:
hibernate:
dialect: org.hibernate.dialect.H2Dialect
format_sql: true
# 缓存配置
demo:
cache:
type: simple
cache-names: products,categories,users
caffeine:
spec: maximumSize=100,expireAfterWrite=10m
```
## 多环境配置文件设计
```yaml
# application-dev.yml - 开发环境配置
spring:
config:
activate:
on-profile: dev
# 开发环境数据源
spring:
datasource:
url: jdbc:mysql://localhost:3306/product_dev?useSSL=false&serverTimezone=Asia/Shanghai&characterEncoding=utf8&allowPublicKeyRetrieval=true
driver-class-name: com.mysql.cj.jdbc.Driver
username: dev_user
password: dev_password
hikari:
maximum-pool-size: 10
minimum-idle: 3
connection-timeout: 30000
idle-timeout: 600000
max-lifetime: 1800000
connection-test-query: SELECT 1
# JPA配置
jpa:
hibernate:
ddl-auto: update
show-sql: true
properties:
hibernate:
dialect: org.hibernate.dialect.MySQL8Dialect
format_sql: true
jdbc:
batch_size: 20
order_inserts: true
order_updates: true
open-in-view: false
# Redis配置
redis:
host: localhost
port: 6379
password: ""
database: 0
timeout: 5000ms
lettuce:
pool:
max-active: 8
max-idle: 8
min-idle: 0
max-wait: -1ms
shutdown-timeout: 100ms
# 消息队列配置
rabbitmq:
host: localhost
port: 5672
username: guest
password: guest
virtual-host: /
connection-timeout: 10000
listener:
simple:
concurrency: 3
max-concurrency: 10
prefetch: 10
retry:
enabled: true
max-attempts: 3
initial-interval: 1000ms
# 邮件配置
mail:
host: smtp.gmail.com
port: 587
username: dev@example.com
password: ${MAIL_PASSWORD:dev_password}
properties:
mail:
smtp:
auth: true
starttls:
enable: true
connectiontimeout: 5000
timeout: 5000
writetimeout: 5000
# 应用特定配置
app:
environment: dev
features:
enable-cache: true
enable-notification: false
enable-audit-log: true
api-rate-limit: 1000
security:
cors:
allowed-origins: "http://localhost:3000,http://localhost:8080"
allowed-methods: "GET,POST,PUT,DELETE,OPTIONS"
allowed-headers: "*"
allow-credentials: true
jwt:
secret: dev_jwt_secret_key_change_in_production
expiration: 86400000 # 24小时
external:
payment-service:
url: http://localhost:8081
timeout: 5000
inventory-service:
url: http://localhost:8082
timeout: 3000
monitoring:
sentry:
dsn: ${SENTRY_DSN:}
enabled: false
new-relic:
enabled: false
# 日志配置覆盖
logging:
level:
com.example: TRACE
org.springframework.web: DEBUG
org.hibernate.SQL: DEBUG
org.hibernate.type: TRACE
file:
name: logs/app-dev.log
```
```yaml
# application-test.yml - 测试环境配置
spring:
config:
activate:
on-profile: test
# 测试环境数据源
spring:
datasource:
url: jdbc:mysql://test-db.example.com:3306/product_test?useSSL=true&serverTimezone=Asia/Shanghai
driver-class-name: com.mysql.cj.jdbc.Driver
username: ${DB_USERNAME:test_user}
password: ${DB_PASSWORD:test_password}
hikari:
maximum-pool-size: 20
minimum-idle: 5
connection-timeout: 30000
idle-timeout: 600000
max-lifetime: 1800000
jpa:
hibernate:
ddl-auto: validate
show-sql: false
properties:
hibernate:
dialect: org.hibernate.dialect.MySQL8Dialect
jdbc:
batch_size: 50
redis:
host: test-redis.example.com
port: 6379
password: ${REDIS_PASSWORD:}
database: 1
timeout: 3000ms
lettuce:
pool:
max-active: 20
max-idle: 10
min-idle: 5
# 测试环境特定配置
app:
environment: test
features:
enable-cache: true
enable-notification: true
enable-audit-log: true
api-rate-limit: 5000
enable-mock-payment: true # 测试环境启用模拟支付
security:
cors:
allowed-origins: "https://test.example.com,https://test-api.example.com"
jwt:
secret: ${JWT_SECRET:test_jwt_secret}
expiration: 3600000 # 1小时
external:
payment-service:
url: https://payment-test.example.com
timeout: 10000
retry:
max-attempts: 3
backoff-delay: 1000
inventory-service:
url: https://inventory-test.example.com
timeout: 5000
# 测试数据
test-data:
enabled: true
location: classpath:test-data/
clean-before-load: true
datasets:
- users.json
- products.json
- orders.json
# 集成测试配置
integration:
test:
timeout: 30000
cleanup:
enabled: true
strategy: transaction
database:
reset:
enabled: true
script: classpath:test-reset.sql
```
```yaml
# application-staging.yml - 预生产环境配置
spring:
config:
activate:
on-profile: staging
# 预生产环境数据源
spring:
datasource:
url: jdbc:mysql://staging-db-cluster.example.com:3306/product_staging?useSSL=true&serverTimezone=Asia/Shanghai
driver-class-name: com.mysql.cj.jdbc.Driver
username: ${DB_USERNAME}
password: ${DB_PASSWORD}
hikari:
maximum-pool-size: 30
minimum-idle: 10
connection-timeout: 30000
idle-timeout: 600000
max-lifetime: 1800000
connection-init-sql: SET NAMES utf8mb4
# 多数据源配置(读写分离)
datasources:
read:
url: jdbc:mysql://staging-db-readonly.example.com:3306/product_staging?useSSL=true
username: ${DB_READ_USERNAME}
password: ${DB_READ_PASSWORD}
hikari:
maximum-pool-size: 20
read-only: true
write:
url: jdbc:mysql://staging-db-master.example.com:3306/product_staging?useSSL=true
username: ${DB_WRITE_USERNAME}
password: ${DB_WRITE_PASSWORD}
hikari:
maximum-pool-size: 15
read-only: false
# 连接池监控
jpa:
hibernate:
ddl-auto: none
show-sql: false
properties:
hibernate:
stats: true
generate_statistics: true
session.events.log: true
# Redis哨兵配置
redis:
sentinel:
master: redis-staging-master
nodes:
- staging-redis-sentinel-1:26379
- staging-redis-sentinel-2:26379
- staging-redis-sentinel-3:26379
password: ${REDIS_PASSWORD}
database: 2
timeout: 5000ms
lettuce:
pool:
max-active: 50
max-idle: 20
min-idle: 10
# 消息队列集群
rabbitmq:
addresses: staging-rabbit-1:5672,staging-rabbit-2:5672
username: ${RABBITMQ_USERNAME}
password: ${RABBITMQ_PASSWORD}
virtual-host: /staging
connection-timeout: 5000
cache:
channel:
size: 25
# 预生产环境应用配置
app:
environment: staging
features:
enable-cache: true
enable-notification: true
enable-audit-log: true
api-rate-limit: 10000
enable-cdn: true
enable-compression: true
security:
cors:
allowed-origins: "https://staging.example.com,https://staging-api.example.com"
jwt:
secret: ${JWT_SECRET}
expiration: 7200000 # 2小时
ssl:
enabled: true
protocols: TLSv1.2,TLSv1.3
rate-limit:
global: 1000
per-user: 100
# 外部服务配置
external:
payment-service:
url: https://payment-staging.example.com
timeout: 15000
circuit-breaker:
enabled: true
failure-threshold: 5
timeout: 10000
inventory-service:
url: https://inventory-staging.example.com
timeout: 10000
retry:
max-attempts: 3
backoff-multiplier: 2.0
# 性能配置
performance:
thread-pool:
core-size: 10
max-size: 50
queue-capacity: 100
cache:
ttl: 300
max-size: 1000
http:
max-connections: 100
timeout: 30000
# 监控配置
monitoring:
sentry:
dsn: ${SENTRY_DSN_STAGING}
enabled: true
environment: staging
new-relic:
enabled: true
app-name: product-service-staging
metrics:
export-interval: 60s
retention: 7d
# Actuator扩展配置
management:
endpoints:
web:
exposure:
include: "*"
jmx:
exposure:
include: "*"
endpoint:
health:
show-details: when-authorized
probes:
enabled: true
metrics:
export:
prometheus:
enabled: true
datadog:
enabled: true
api-key: ${DATADOG_API_KEY}
metrics:
tags:
environment: staging
region: ${CLOUD_REGION:cn-east-1}
distribution:
percentiles-histogram:
http.server.requests: true
```
```yaml
# application-prod.yml - 生产环境配置
spring:
config:
activate:
on-profile: prod
# 生产环境数据源
spring:
datasource:
url: jdbc:mysql://prod-db-cluster.example.com:3306/product_prod?useSSL=true&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true
driver-class-name: com.mysql.cj.jdbc.Driver
username: ${PROD_DB_USERNAME}
password: ${PROD_DB_PASSWORD}
hikari:
maximum-pool-size: 50
minimum-idle: 20
connection-timeout: 30000
idle-timeout: 600000
max-lifetime: 1800000
connection-init-sql: SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci
leak-detection-threshold: 60000
validation-timeout: 5000
connection-test-query: SELECT 1 FROM DUAL
# 生产环境多数据源
datasources:
read:
url: jdbc:mysql://prod-db-ro-cluster.example.com:3306/product_prod?useSSL=true
username: ${PROD_DB_READ_USERNAME}
password: ${PROD_DB_READ_PASSWORD}
hikari:
maximum-pool-size: 40
minimum-idle: 15
read-only: true
connection-timeout: 10000
write:
url: jdbc:mysql://prod-db-rw-cluster.example.com:3306/product_prod?useSSL=true
username: ${PROD_DB_WRITE_USERNAME}
password: ${PROD_DB_WRITE_PASSWORD}
hikari:
maximum-pool-size: 30
minimum-idle: 10
read-only: false
connection-timeout: 15000
# JPA生产配置
jpa:
hibernate:
ddl-auto: validate
show-sql: false
properties:
hibernate:
dialect: org.hibernate.dialect.MySQL8Dialect
jdbc:
batch_size: 100
order_inserts: true
order_updates: true
jdbc.batch_versioned_data: true
generate_statistics: true
cache:
use_second_level_cache: true
use_query_cache: true
region.factory_class: org.hibernate.cache.jcache.JCacheRegionFactory
open-in-view: false
# Redis集群配置
redis:
cluster:
nodes:
- prod-redis-node-1:6379
- prod-redis-node-2:6379
- prod-redis-node-3:6379
- prod-redis-node-4:6379
- prod-redis-node-5:6379
- prod-redis-node-6:6379
max-redirects: 3
password: ${PROD_REDIS_PASSWORD}
timeout: 3000ms
lettuce:
pool:
max-active: 100
max-idle: 50
min-idle: 20
max-wait: 5000ms
cluster:
refresh:
adaptive: true
period: 30000
# RabbitMQ生产配置
rabbitmq:
addresses: prod-rabbit-1:5672,prod-rabbit-2:5672,prod-rabbit-3:5672
username: ${PROD_RABBITMQ_USERNAME}
password: ${PROD_RABBITMQ_PASSWORD}
virtual-host: /prod
connection-timeout: 10000
publisher-confirm-type: correlated
publisher-returns: true
listener:
simple:
concurrency: 5
max-concurrency: 20
prefetch: 50
acknowledge-mode: manual
retry:
enabled: true
max-attempts: 5
initial-interval: 3000ms
multiplier: 2.0
<"j2.p5k3.org.cn"><"n5.p5k3.org.cn"><"w1.p5k3.org.cn">
# 邮件生产配置
mail:
host: smtp.exmail.qq.com
port: 465
username: ${PROD_MAIL_USERNAME}
password: ${PROD_MAIL_PASSWORD}
protocol: smtps
properties:
mail:
smtp:
auth: true
ssl:
enable: true
socketFactory:
class: javax.net.ssl.SSLSocketFactory
connectiontimeout: 10000
timeout: 10000
writetimeout: 10000
# 安全配置
security:
oauth2:
resourceserver:
jwt:
issuer-uri: https://auth.example.com
jwk-set-uri: https://auth.example.com/.well-known/jwks.json
# 生产环境应用配置
app:
environment: prod
version: ${APP_VERSION:1.0.0}
features:
enable-cache: true
enable-notification: true
enable-audit-log: true
api-rate-limit: 50000
enable-cdn: true
enable-compression: true
enable-gzip: true
enable-http2: true
enable-response-cache: true
security:
cors:
allowed-origins: "https://example.com,https://api.example.com"
allowed-methods: "GET,POST,PUT,DELETE,OPTIONS"
allowed-headers: "Authorization,Content-Type,X-Requested-With,Accept,Origin"
exposed-headers: "X-Total-Count,X-Page-Count"
max-age: 3600
jwt:
secret: ${PROD_JWT_SECRET}
expiration: 3600000 # 1小时
refresh-expiration: 2592000000 # 30天
rate-limit:
enabled: true
global: 5000
per-user: 200
per-ip: 1000
ssl:
enabled: true
protocols: TLSv1.3
ciphers: TLS_AES_256_GCM_SHA384,TLS_CHACHA20_POLY1305_SHA256
# 外部服务生产配置
external:
payment-service:
url: https://payment.example.com
timeout: 30000
circuit-breaker:
enabled: true
failure-threshold: 10
timeout: 20000
reset-timeout: 60000
retry:
max-attempts: 3
backoff:
delay: 1000
multiplier: 2.0
max-delay: 10000
inventory-service:
url: https://inventory.example.com
timeout: 20000
load-balancer:
strategy: round-robin
health-check:
enabled: true
interval: 30000
# 性能优化配置
performance:
thread-pool:
core-size: 20
max-size: 100
queue-capacity: 200
keep-alive-time: 60s
cache:
ttl: 600
max-size: 10000
caffeine:
spec: maximumSize=10000,expireAfterWrite=600s
http:
client:
max-connections: 200
max-connections-per-route: 50
connection-timeout: 10000
socket-timeout: 30000
connection-request-timeout: 10000
server:
max-threads: 200
min-spare-threads: 20
connection-timeout: 30000
max-connections: 10000
max-http-header-size: 16KB
compression:
enabled: true
mime-types: text/html,text/xml,text/plain,text/css,text/javascript,application/json,application/javascript,application/xml
min-response-size: 1024
# 监控告警配置
monitoring:
sentry:
dsn: ${PROD_SENTRY_DSN}
enabled: true
environment: production
release: ${APP_VERSION}
traces-sample-rate: 0.1
new-relic:
enabled: true
app-name: product-service-prod
license-key: ${NEW_RELIC_LICENSE_KEY}
datadog:
enabled: true
api-key: ${DATADOG_API_KEY}
site: datadoghq.com
metrics:
export-interval: 30s
retention: 30d
percentiles: 0.5,0.95,0.99
alert:
enabled: true
webhook: ${ALERT_WEBHOOK_URL}
rules:
error-rate:
threshold: 5%
window: 5m
response-time:
p95-threshold: 2000ms
window: 10m
system:
cpu-threshold: 80%
memory-threshold: 85%
disk-threshold: 90%
# 审计日志配置
audit:
enabled: true
level: INFO
max-size: 100MB
retention: 90d
format: json
include:
- request
- response
- user
- timestamp
- duration
# Actuator生产配置
management:
server:
port: 8081
address: 127.0.0.1
ssl:
enabled: true
key-store: classpath:keystore.p12
key-store-password: ${ACTUATOR_KEYSTORE_PASSWORD}
key-store-type: PKCS12
endpoints:
web:
exposure:
include: health,info,metrics,prometheus
base-path: /internal
path-mapping:
health: health-check
access:
rules:
- endpoint: health
access: unrestricted
- endpoint: info
access: authenticated
- endpoint: metrics
access: admin
jmx:
exposure:
include: health,info,metrics
domain: com.example.prod
endpoint:
health:
show-details: when-authorized
show-components: when-authorized
roles: ADMIN,OPERATOR
group:
liveness:
include: ping,livenessState,diskSpace
readiness:
include: ping,readinessState,db,redis,mq,custom
probes:
enabled: true
metrics:
enabled: true
distribution:
percentiles-histogram:
http.server.requests: true
jvm.gc.pause: true
slo:
http.server.requests: 100ms,500ms,1s,5s
prometheus:
enabled: true
step: 15s
metrics:
export:
prometheus:
enabled: true
step: 15s
datadog:
enabled: true
api-key: ${DATADOG_API_KEY}
step: 30s
tags:
application: product-service
environment: production
region: ${CLOUD_REGION}
zone: ${CLOUD_ZONE}
instance: ${HOSTNAME:${spring.application.instance-id:${random.value}}}
distribution:
percentiles:
http.server.requests: 0.5,0.95,0.99
percentiles-histogram:
http.server.requests: true
jvm.gc.pause: true
tracing:
sampling:
probability: 0.01
propagation:
type: B3,W3C
# 日志生产配置
logging:
level:
root: WARN
com.example: INFO
org.springframework.web: WARN
org.hibernate: ERROR
org.apache.kafka: WARN
org.springframework.amqp: WARN
pattern:
console: "%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} [%X{traceId:-},%X{spanId:-}] - %msg%n"
file: "%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} [%X{traceId:-},%X{spanId:-}] - %msg%n"
logback:
rollingpolicy:
max-file-size: 100MB
max-history: 30
total-size-cap: 3GB
clean-history-on-start: true
file:
name: /var/log/product-service/app.log
log-dir: /var/log/product-service/
```
## Profile激活与配置覆盖策略
```java
// ProfileConfiguration.java - Profile配置类
package com.example.config;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.env.EnvironmentPostProcessor;
import org.springframework.boot.env.YamlPropertySourceLoader;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.PropertySource;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
@Configuration
public class ProfileConfiguration {
// 自定义属性源加载器
@Component
public static class CustomEnvironmentPostProcessor implements EnvironmentPostProcessor {
private final YamlPropertySourceLoader loader = new YamlPropertySourceLoader();
@Override
public void postProcessEnvironment(ConfigurableEnvironment environment,
SpringApplication application) {
// 根据激活的profiles加载特定配置
List
// 加载优先级:外部配置 > 环境变量 > 配置文件
loadProfileSpecificConfig(environment, activeProfiles);
// 加载租户特定配置(多租户场景)
loadTenantConfig(environment);
// 设置配置验证
validateConfiguration(environment);
}
private void loadProfileSpecificConfig(ConfigurableEnvironment environment,
List
// 基础配置
loadYamlResource(environment, "classpath:application.yml");
// Profile特定配置
for (String profile : activeProfiles) {
String configFile = String.format("classpath:application-%s.yml", profile);
loadYamlResource(environment, configFile);
// 加载可选的本地覆盖配置
String localConfig = String.format("classpath:application-%s-local.yml", profile);
loadYamlResourceOptional(environment, localConfig);
}
// 加载外部配置文件
String externalConfig = System.getProperty("config.location");
if (externalConfig != null) {
loadYamlResource(environment, "file:" + externalConfig);
}
}
private void loadTenantConfig(ConfigurableEnvironment environment) {
String tenantId = environment.getProperty("app.tenant.id");
if (tenantId != null) {
String tenantConfig = String.format("classpath:tenant/application-%s.yml", tenantId);
loadYamlResourceOptional(environment, tenantConfig);
}
}
<"g8.p5k3.org.cn"><"q0.p5k3.org.cn"><"t4.p5k3.org.cn">
private void loadYamlResource(ConfigurableEnvironment environment, String location) {
try {
Resource resource = new ClassPathResource(location.replace("classpath:", ""));
if (resource.exists()) {
List
sources.forEach(environment.getPropertySources()::addLast);
}
} catch (IOException e) {
throw new IllegalStateException("加载配置文件失败: " + location, e);
}
}
private void loadYamlResourceOptional(ConfigurableEnvironment environment, String location) {
try {
Resource resource = new ClassPathResource(location.replace("classpath:", ""));
if (resource.exists()) {
List
sources.forEach(environment.getPropertySources()::addLast);
}
} catch (IOException e) {
// 可选配置,忽略错误
}
}
private void validateConfiguration(ConfigurableEnvironment environment) {
// 配置验证逻辑
String requiredProperty = environment.getProperty("app.required.property");
if (requiredProperty == null) {
throw new IllegalStateException("缺少必需的配置属性: app.required.property");
}
}
}
// Profile激活策略配置
@Bean
@Profile("dev")
public DataSource devDataSource() {
// 开发环境数据源
HikariDataSource dataSource = new HikariDataSource();
dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/dev");
dataSource.setUsername("dev_user");
dataSource.setPassword("dev_password");
dataSource.setMaximumPoolSize(10);
return dataSource;
}
@Bean
@Profile("prod")
public DataSource prodDataSource() {
// 生产环境数据源
HikariDataSource dataSource = new HikariDataSource();
dataSource.setJdbcUrl("jdbc:mysql://prod-cluster:3306/prod");
dataSource.setUsername(System.getenv("DB_USERNAME"));
dataSource.setPassword(System.getenv("DB_PASSWORD"));
dataSource.setMaximumPoolSize(50);
return dataSource;
}
// 条件配置示例
@Configuration
@ConditionalOnProperty(name = "app.features.enable-cache", havingValue = "true")
@ConditionalOnClass(RedisConnectionFactory.class)
public static class CacheConfiguration {
@Bean
@Profile({"dev", "test"})
public CacheManager simpleCacheManager() {
return new ConcurrentMapCacheManager("products", "categories");
}
@Bean
@Profile({"staging", "prod"})
public CacheManager redisCacheManager(RedisConnectionFactory connectionFactory) {
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofMinutes(10))
.serializeValuesWith(RedisSerializationContext.SerializationPair
.fromSerializer(RedisSerializer.json()));
return RedisCacheManager.builder(connectionFactory)
.cacheDefaults(config)
.build();
}
}
}
// 应用启动类
@SpringBootApplication
public class ProductServiceApplication {
public static void main(String[] args) {
SpringApplication app = new SpringApplication(ProductServiceApplication.class);
// 设置默认Profile
app.setDefaultProperties(Collections.singletonMap(
"spring.profiles.default", "dev"
));
// 启动应用
app.run(args);
}
// Profile激活监听器
@EventListener
public void handleApplicationStarted(ApplicationStartedEvent event) {
ConfigurableEnvironment env = event.getApplicationContext().getEnvironment();
String[] activeProfiles = env.getActiveProfiles();
log.info("激活的Profiles: {}", Arrays.toString(activeProfiles));
log.info("当前环境: {}", env.getProperty("app.environment"));
log.info("应用名称: {}", env.getProperty("spring.application.name"));
// 根据Profile执行初始化逻辑
if (Arrays.asList(activeProfiles).contains("dev")) {
initializeDevelopmentEnvironment();
} else if (Arrays.asList(activeProfiles).contains("prod")) {
initializeProductionEnvironment();
}
}
private void initializeDevelopmentEnvironment() {
log.info("初始化开发环境...");
// 开发环境特定的初始化逻辑
}
private void initializeProductionEnvironment() {
log.info("初始化生产环境...");
// 生产环境特定的初始化逻辑
}
}
```
## 部署与运行配置
```bash
#!/bin/bash
# deploy.sh - 多环境部署脚本
# 环境变量配置
ENVIRONMENT=${ENVIRONMENT:-dev}
CONFIG_DIR="/app/config"
LOG_DIR="/app/logs"
# 根据环境选择配置
case $ENVIRONMENT in
"dev")
PROFILE="dev"
JAVA_OPTS="-Xmx512m -Xms256m"
;;
"test")
PROFILE="test"
JAVA_OPTS="-Xmx1g -Xms512m"
;;
"staging")
PROFILE="staging"
JAVA_OPTS="-Xmx2g -Xms1g"
;;
"prod")
PROFILE="prod"
JAVA_OPTS="-Xmx4g -Xms2g -XX:+UseG1GC -XX:MaxGCPauseMillis=200"
;;
*)
echo "未知环境: $ENVIRONMENT"
exit 1
;;
esac
# 创建目录
mkdir -p $CONFIG_DIR $LOG_DIR
# 复制配置文件
cp /app/resources/application-$PROFILE.yml $CONFIG_DIR/application.yml
# 导出环境变量
export SPRING_PROFILES_ACTIVE=$PROFILE
export SPRING_CONFIG_LOCATION=$CONFIG_DIR/
export LOGGING_FILE_NAME=$LOG_DIR/app.log
export JAVA_OPTS
# 启动应用
java $JAVA_OPTS \
-Dspring.profiles.active=$PROFILE \
-Dspring.config.location=$CONFIG_DIR/ \
-Dlogging.file.name=$LOG_DIR/app.log \
-jar /app/product-service.jar
```
```dockerfile
# Dockerfile多环境构建
FROM openjdk:17-jdk-slim as builder
# 构建阶段
WORKDIR /app
COPY . .
RUN ./gradlew clean bootJar
FROM openjdk:17-jre-slim
# 运行时环境变量
ARG ENVIRONMENT=dev
ENV SPRING_PROFILES_ACTIVE=${ENVIRONMENT}
ENV JAVA_OPTS="-XX:+UseContainerSupport -XX:MaxRAMPercentage=75.0"
# 创建非root用户
RUN groupadd -r spring && useradd -r -g spring spring
USER spring:spring
WORKDIR /app
COPY --from=builder /app/build/libs/*.jar app.jar
# 配置文件目录
VOLUME /app/config
VOLUME /app/logs
# 健康检查
HEALTHCHECK --interval=30s --timeout=3s --start-period=60s --retries=3 \
CMD curl -f http://localhost:8080/actuator/health || exit 1
# 启动命令
ENTRYPOINT ["sh", "-c", "java $JAVA_OPTS -Dspring.profiles.active=$SPRING_PROFILES_ACTIVE -jar app.jar"]
```
基于Spring Boot Profile的多环境配置机制,为企业应用提供了灵活、安全的配置管理方案。通过分级配置、条件装配和环境隔离,实现了从开发到生产的全生命周期配置管理。在实际应用中,需要结合配置中心、密钥管理和持续部署工具,构建完整的配置管理体系,确保应用在不同环境中的一致性和安全性。