配置管理
问题
Spring Boot 的配置文件有哪些?配置的优先级是什么?如何实现多环境配置?
答案
配置文件类型
| 类型 | 文件名 | 特点 |
|---|---|---|
| Properties | application.properties | key=value 格式,简单直接 |
| YAML | application.yml | 层级结构,可读性强 |
server:
port: 8080
servlet:
context-path: /api
spring:
datasource:
url: jdbc:mysql://localhost:3306/mydb
username: root
password: 123456
redis:
host: localhost
port: 6379
配置优先级(从高到低)
Spring Boot 支持 17 种配置源,常用的优先级排列如下:
- 高优先级覆盖低优先级
- Profile 配置覆盖默认配置
- jar 包外的配置覆盖 jar 包内的(方便运维不修改代码调整配置)
多环境配置(Profile)
spring:
profiles:
active: dev # 默认激活 dev 环境
server:
port: 8080
spring:
datasource:
url: jdbc:mysql://localhost:3306/mydb
logging:
level:
root: DEBUG
server:
port: 80
spring:
datasource:
url: jdbc:mysql://prod-db:3306/mydb
logging:
level:
root: WARN
激活 Profile 的方式:
# 命令行参数(最常用)
java -jar app.jar --spring.profiles.active=prod
# 环境变量
export SPRING_PROFILES_ACTIVE=prod
# JVM 参数
java -Dspring.profiles.active=prod -jar app.jar
@ConfigurationProperties 绑定
将配置文件属性批量绑定到 Java 对象:
@ConfigurationProperties(prefix = "my.app")
@Validated // 开启参数校验
public class MyAppProperties {
/** 应用名称 */
@NotBlank
private String name;
/** 最大重试次数 */
@Min(1) @Max(10)
private int maxRetry = 3;
/** 超时时间 */
private Duration timeout = Duration.ofSeconds(30);
/** 嵌套配置 */
private final Security security = new Security();
public static class Security {
private String apiKey;
private List<String> allowedOrigins = List.of("*");
// getter/setter...
}
// getter/setter...
}
my:
app:
name: MyApplication
max-retry: 5
timeout: 60s
security:
api-key: sk-xxx
allowed-origins:
- https://example.com
- https://api.example.com
@Service
public class MyService {
private final MyAppProperties properties;
public MyService(MyAppProperties properties) {
this.properties = properties;
}
public void doSomething() {
String apiKey = properties.getSecurity().getApiKey();
// 使用配置值...
}
}
@Value vs @ConfigurationProperties
| 对比 | @Value | @ConfigurationProperties |
|---|---|---|
| 使用方式 | 单个属性注入 | 批量绑定到对象 |
| 松散绑定 | 不支持 | 支持(max-retry = maxRetry) |
| SpEL 表达式 | 支持 | 不支持 |
| 校验 | 不支持 | 支持 @Validated |
| 复杂类型 | 不支持 | 支持(Map、List、嵌套对象) |
| 适用场景 | 个别属性注入 | 一组相关配置 |
优先使用 @ConfigurationProperties,它类型安全、支持校验、支持 IDE 自动提示(通过 spring-boot-configuration-processor 生成元数据)。
配置加密
敏感配置(数据库密码、API Key)不应明文存储:
spring:
datasource:
# ENC() 包裹的值会被自动解密
password: ENC(4jJ1D2s3kF5hX7...)
jasypt:
encryptor:
password: ${JASYPT_PASSWORD} # 解密密钥从环境变量获取
常见面试问题
Q1: Spring Boot 配置文件的加载优先级?
答案:
从高到低:命令行参数 > Java 系统属性 > 环境变量 > jar 包外的 profile 配置 > jar 包内的 profile 配置 > jar 包外的默认配置 > jar 包内的默认配置 > @ConfigurationProperties 默认值。核心原则是:外部配置优先于内部,Profile 配置优先于默认。
Q2: @Value 和 @ConfigurationProperties 的区别?
答案:
@Value 逐个注入属性值,支持 SpEL 但不支持校验和松散绑定。@ConfigurationProperties 批量绑定到对象,支持松散绑定(max-retry 自动匹配 maxRetry)、JSR-303 校验、复杂类型(List/Map/嵌套),推荐优先使用。
Q3: 如何实现多环境配置?
答案:
使用 Profile 机制。创建 application-{profile}.yml(如 dev、test、prod),通过 spring.profiles.active 指定激活的环境。激活方式包括:配置文件、命令行参数 --spring.profiles.active=prod、环境变量 SPRING_PROFILES_ACTIVE。
Q4: 配置文件中的敏感信息如何处理?
答案:
常见方案:
- 环境变量:通过
${DB_PASSWORD}引用系统环境变量 - 配置中心:使用 Nacos/Apollo 等配置中心管理,支持加密和动态刷新
- Jasypt 加密:在配置文件中使用
ENC(密文),运行时自动解密 - Vault:使用 HashiCorp Vault 等密钥管理服务
Q5: 松散绑定(Relaxed Binding)是什么?
答案:
@ConfigurationProperties 支持多种属性名风格自动匹配:
| 配置文件写法 | Java 属性名 |
|---|---|
my.app.max-retry | maxRetry(推荐用短横线分隔) |
my.app.maxRetry | maxRetry |
my.app.MAX_RETRY | maxRetry(环境变量风格) |
my.app.max_retry | maxRetry |
相关链接
- Spring Boot 官方文档 - 外部化配置
- 自动配置原理 - @EnableConfigurationProperties
- Spring 常用注解 - @Value、@ConfigurationProperties