Spring Boot: 配置管理
最后更新:2026-08-26
配置管理是应用从开发到生产的桥梁——一套代码,多套配置,环境切换只需一行参数。
1. 你将学到
- Profile 机制:
application-dev.yml/application-prod.yml多环境切换 @ConfigurationProperties类型安全绑定与@Value注入对比- 配置优先级层级:命令行参数 > 环境变量 > 配置文件 > 默认值
- 嵌套配置与 List/Map 类型绑定
- OrderFlow 数据源与第三方 API 密钥的外部化配置实践
2. 一个运维工程师的真实故事
(1) 痛点:配置散落各处
Bob 是 OrderFlow 的运维工程师,每次部署都像"考古":数据库密码硬编码在代码里,测试环境和生产环境的配置混在一个文件中,有人改了生产数据库密码却忘了更新代码,导致系统宕机 2 小时。Charlie 追问 SLA,Bob 只能无奈地解释"配置管理混乱"。
(2) Spring Boot Profile 的解法
Spring Boot 用 Profile 机制分离多环境配置:
YAML
# application-dev.yml
spring:
datasource:
url: jdbc:mysql://localhost:3306/orderflow_dev
username: dev_user
password: dev_pass
YAML
# application-prod.yml
spring:
datasource:
url: jdbc:mysql://prod-db.internal:3306/orderflow
username: ${DB_USERNAME}
password: ${DB_PASSWORD}
(3) 收益
Bob 用 Profile + 环境变量重构后,开发环境用 dev、生产用 prod,敏感信息不再出现在代码仓库中,部署切换只需 --spring.profiles.active=prod,配置错误导致的宕机时间降为零。
3. Profile 多环境配置
(1) Profile 文件命名规则
Spring Boot 按 application-{profile}.yml 命名约定加载 Profile 配置:
TEXT
📖 仅展示
src/main/resources/
├── application.yml # Common config (shared)
├── application-dev.yml # Dev profile
├── application-prod.yml # Prod profile
└── application-test.yml # Test profile
graph TD
A["application.yml<br/>Common Config"] --> B["application-dev.yml<br/>Dev Overrides"]
A --> C["application-prod.yml<br/>Prod Overrides"]
A --> D["application-test.yml<br/>Test Overrides"]
B --> E["Merged Config<br/>Profile=dev"]
C --> F["Merged Config<br/>Profile=prod"]
| 激活方式 | 命令 | 优先级 |
|---|---|---|
| 配置文件 | spring.profiles.active=dev in application.yml |
最低 |
| 环境变量 | SPRING_PROFILES_ACTIVE=dev |
中 |
| 命令行参数 | --spring.profiles.active=dev |
最高 |
▶ 示例: Profile 配置文件
YAML
# application.yml (shared)
spring:
application:
name: orderflow-service
profiles:
active: dev
server:
port: 8080
输出:
TEXT
📖 仅展示
Configuration applied successfully
YAML
# application-dev.yml
spring:
datasource:
url: jdbc:h2:mem:orderflow_dev
username: sa
password:
jpa:
hibernate:
ddl-auto: create-drop
show-sql: true
logging:
level:
com.orderflow: DEBUG
YAML
# application-prod.yml
spring:
datasource:
url: jdbc:mysql://${DB_HOST:localhost}:3306/orderflow
username: ${DB_USERNAME}
password: ${DB_PASSWORD}
jpa:
hibernate:
ddl-auto: validate
show-sql: false
logging:
level:
com.orderflow: WARN
4. @Value 与 @ConfigurationProperties 对比
(1) 两种注入方式
▶ 示例: @Value 注入
JAVA
@RestController
public class OrderController {
@Value("${orderflow.max-items-per-order:100}")
private int maxItemsPerOrder;
@Value("${orderflow.default-currency:USD}")
private String defaultCurrency;
@GetMapping("/api/config/check")
public Map<String, Object> checkConfig() {
return Map.of(
"maxItemsPerOrder", maxItemsPerOrder,
"defaultCurrency", defaultCurrency
);
}
}
输出:
TEXT
📖 仅展示
// 执行成功
▶ 示例: @ConfigurationProperties 类型安全绑定
JAVA
@ConfigurationProperties(prefix = "orderflow")
public record OrderFlowProperties(
int maxItemsPerOrder,
String defaultCurrency,
Duration orderTimeout,
ShippingConfig shipping
) {
public record ShippingConfig(
boolean freeShippingEnabled,
BigDecimal freeShippingThreshold
) {}
}
// Enable in main class or config class
@EnableConfigurationProperties(OrderFlowProperties.class)
输出:
TEXT
📖 仅展示
// 执行成功
| 维度 | @Value |
@ConfigurationProperties |
|---|---|---|
| 类型安全 | 弱(String 为主) | 强(自动类型转换) |
| 嵌套对象 | 不支持 | 支持 |
| 集合绑定 | 不支持 | 支持 List/Map |
| 校验 | 无 | 配合 @Validated |
| IDE 支持 | 无提示 | 有自动补全(metadata) |
| 适用场景 | 少量简单值 | 结构化业务配置 |
▶ 示例: YAML 与 ConfigurationProperties 对应
YAML
orderflow:
max-items-per-order: 50
default-currency: USD
order-timeout: 30m
shipping:
free-shipping-enabled: true
free-shipping-threshold: 49.99
输出:
TEXT
📖 仅展示
配置文件已生效
JAVA
// Access example
@Component
public class OrderService {
private final OrderFlowProperties props;
public OrderService(OrderFlowProperties props) {
this.props = props;
}
public boolean isFreeShipping(BigDecimal orderTotal) {
return props.shipping().freeShippingEnabled()
&& orderTotal.compareTo(props.shipping().freeShippingThreshold()) >= 0;
}
}
5. 配置优先级层级
(1) 优先级从高到低
graph TD
A["1. Command Line Args<br/>--server.port=9090"] --> B["2. JNDI Attributes"]
B --> C["3. Java System Properties<br/>-Dserver.port=9090"]
C --> D["4. OS Environment Variables<br/>SERVER_PORT=9090"]
D --> E["5. application-{profile}.yml<br/>Profile-specific"]
E --> F["6. application.yml<br/>Default config"]
F --> G["7. @Default Values<br/>In code annotations"]
| 优先级 | 来源 | 示例 |
|---|---|---|
| 1(最高) | 命令行参数 | --server.port=9090 |
| 2 | JNDI 属性 | java:comp/env/... |
| 3 | JVM 系统属性 | -Dserver.port=9090 |
| 4 | OS 环境变量 | SERVER_PORT=9090 |
| 5 | Profile 配置文件 | application-prod.yml |
| 6 | 默认配置文件 | application.yml |
| 7(最低) | 代码默认值 | @Value("${x:default}") |
💡 提示: 生产环境推荐用环境变量或命令行参数覆盖敏感配置,不要把密码写在配置文件中。
6. 嵌套配置与集合绑定
(1) List 和 Map 绑定
▶ 示例: List 和 Map 配置
YAML
orderflow:
supported-currencies:
- USD
- EUR
- GBP
payment-gateways:
stripe:
api-key: ${STRIPE_API_KEY}
webhook-secret: ${STRIPE_WEBHOOK_SECRET}
paypal:
client-id: ${PAYPAL_CLIENT_ID}
secret: ${PAYPAL_SECRET}
输出:
TEXT
📖 仅展示
CI/CD 流水线配置已加载
Pipeline 运行状态: passed
Tests: 12 passed, 0 failed
JAVA
@ConfigurationProperties(prefix = "orderflow")
public record OrderFlowProperties(
List<String> supportedCurrencies,
Map<String, GatewayConfig> paymentGateways
) {
public record GatewayConfig(
String apiKey,
String webhookSecret,
String clientId,
String secret
) {}
}
7. 综合示例:OrderFlow 完整配置体系
JAVA
// OrderFlowProperties.java
package com.orderflow.config;
import org.springframework.boot.context.properties.ConfigurationProperties;
import java.math.BigDecimal;
import java.time.Duration;
import java.util.List;
import java.util.Map;
@ConfigurationProperties(prefix = "orderflow")
public record OrderFlowProperties(
int maxItemsPerOrder,
String defaultCurrency,
Duration orderTimeout,
ShippingConfig shipping,
List<String> supportedCurrencies,
Map<String, GatewayConfig> paymentGateways
) {
public record ShippingConfig(
boolean freeShippingEnabled,
BigDecimal freeShippingThreshold
) {}
public record GatewayConfig(
String apiKey,
String webhookSecret,
String clientId,
String secret
) {}
}
// AppConfig.java
package com.orderflow.config;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Configuration;
@Configuration
@EnableConfigurationProperties(OrderFlowProperties.class)
public class AppConfig {}
YAML
# application.yml
spring:
application:
name: orderflow-service
profiles:
active: dev
orderflow:
max-items-per-order: 50
default-currency: USD
order-timeout: 30m
supported-currencies:
- USD
- EUR
- GBP
shipping:
free-shipping-enabled: true
free-shipping-threshold: 49.99
payment-gateways:
stripe:
api-key: ${STRIPE_API_KEY:dev-key}
webhook-secret: ${STRIPE_WEBHOOK_SECRET:dev-secret}
❓ 常见问题
Q @ConfigurationProperties 和 @Value 该选哪个?
A 结构化配置用 @ConfigurationProperties(类型安全、嵌套、IDE 支持),少量简单值用 @Value。一个项目不要混用太多。
Q 如何防止敏感信息泄露到代码仓库?
A 1)配置文件中使用 ${ENV_VAR} 占位符引用环境变量;2).gitignore 排除敏感配置文件;3)生产环境用 K8s Secret 或 Vault 管理密钥。
Q Profile 配置和默认配置如何合并?
A Spring Boot 先加载默认配置,再用 Profile 配置覆盖相同属性。不同属性互补,相同属性 Profile 优先。
Q YAML 中的 List 在 Properties 中怎么写?
A
orderflow.supported-currencies[0]=USD、orderflow.supported-currencies[1]=EUR。List 索引从 0 开始。Q 如何在代码中动态切换 Profile?
A 不推荐在代码中动态切换。Profile 应在启动时确定。如果需要运行时动态切换配置,使用 Spring Cloud Config 或自定义配置刷新机制。
Q record 作为 ConfigurationProperties 有什么限制?
A record 是不可变的,适合只读配置。Spring Boot 3.x 支持 record 绑定。但无法配合
@Validated 进行 JSR-380 校验(record 无无参构造器),需要用类替代。📖 小节
- Profile 机制实现多环境配置分离,
application-{profile}.yml覆盖默认配置 @ConfigurationProperties类型安全绑定优于@Value,支持嵌套、集合、校验- 配置优先级:命令行 > 环境变量 > Profile 文件 > 默认文件 > 代码默认值
- 敏感信息使用
${ENV_VAR}占位符,不要硬编码到配置文件 - Spring Boot 3.x 支持 record 作为 ConfigurationProperties
📝 作业
-
基础题(难度⭐):为 OrderFlow 配置 dev 和 prod 两个 Profile,dev 使用 H2 内存数据库,prod 使用 MySQL,通过命令行参数切换。
-
进阶题(难度⭐⭐):使用
@ConfigurationProperties创建PaymentGatewayProperties,包含 Stripe 和 PayPal 的 API 密钥配置,通过环境变量注入密钥值。 -
挑战题(难度⭐⭐⭐):实现自定义 PropertySource,从远程配置中心(可用 mock HTTP 接口)加载配置,思考 Spring Boot Environment 抽象的设计意图。