外观
Spring Boot 配置管理
约 1884 字大约 6 分钟
2025-08-16
一、为什么需要专业配置管理
在项目开发中,硬编码配置存在明显问题:
- 部署到不同环境需要手动修改代码
- 敏感信息(如数据库密码)直接暴露在代码中
- 配置修改需要重新编译打包
而 Spring Boot 的配置管理能够:
- 实现配置与代码分离
- 支持多环境差异化配置
- 提供安全的敏感信息管理
- 灵活调整应用行为无需重新部署
二、配置来源与优先级
1. 配置来源
Spring Boot 支持多种配置来源,按优先级从高到低排列:
| 优先级 | 配置来源 | 说明 |
|---|---|---|
| 1 | 命令行参数 | java -jar app.jar --server.port=8081 |
| 2 | application-{profile}.properties/yml | 指定环境的配置文件 |
| 3 | application.properties/yml | 通用配置文件 |
| 4 | jar 包内配置文件 | 打包在 jar 中的配置 |
| 5 | jar 包外配置文件 | 外部配置目录中的配置 |
2. 配置加载顺序
当多个位置存在相同配置项时,高优先级配置会覆盖低优先级配置。
推荐实践:
- 将通用配置放在
application.yml - 将环境特定配置放在
application-{env}.yml - 开发时使用命令行参数快速覆盖配置
三、配置文件格式
1. Properties 格式
# 基本配置
server.port=8080
spring.datasource.url=jdbc:mysql://localhost:3306/test
spring.datasource.username=root
# 随机值配置
my.secret=${random.value}
my.number=${random.int}
my.bignumber=${random.long}
my.test1=${random.int(10)}
my.test2=${random.int[10,20]}2. YAML 格式(推荐)
server:
port: 8080
spring:
datasource:
url: jdbc:mysql://localhost:3306/test
username: root
password: ENC(encrypted-password) # 加密后的密码
my:
secret: ${random.value}
number: ${random.int}
test1: ${random.int(10)}
test2: ${random.int[10,20]}
# 参数引用
book:
name: Spring Boot
author: John Doe
desc: "${book.author} is writing《${book.name}》"YAML 优势:
- 层次结构清晰,可读性高
- 支持复杂数据结构(列表、映射等)
- 支持注释(Properties 不支持)
- 配置量通常比 Properties 少 30-50%
注意:YAML 对缩进敏感,必须使用空格(不能用 Tab)
四、读取配置的常用方法
1. @Value 注解(单个配置)
@Component
public class AppConfig {
@Value("${server.port}")
private int port;
@Value("${my.secret}")
private String secret;
@Value("${book.desc:Default Description}")
private String desc; // 提供默认值
// 注意:@Value 不支持静态变量直接注入
private static String staticValue;
@Value("${my.url}")
public void setStaticValue(String url) {
staticValue = url;
}
}适用场景:
- 简单应用中读取少量配置
- 需要 SpEL 表达式的场景(如
@Value("#{${my.number} > 10}"))
2. @ConfigurationProperties(批量配置)
@Component
@ConfigurationProperties(prefix = "spring.datasource")
@Getter
@Setter
public class DataSourceProperties {
private String url;
private String username;
private String password;
private String driverClassName;
// 可以添加自定义验证逻辑
@PostConstruct
public void init() {
if (url == null || url.isEmpty()) {
throw new IllegalArgumentException("Datasource URL must not be empty");
}
}
}优势:
- 类型安全:自动类型转换
- 松散绑定:支持
kebab-case、camelCase等多种命名方式 - 支持 JSR-303 验证
- IDE 友好:提供代码提示
推荐实践:
- 为每组相关配置创建专用配置类
- 添加
@Validated注解启用验证 - 使用 Lombok 简化 getter/setter
3. 两种方式对比
| 特性 | @ConfigurationProperties | @Value |
|---|---|---|
| 松散绑定 | ✅ 支持 (如 my-prop 可映射到 myProp) | ❌ 不支持 |
| 类型转换 | ✅ 自动转换 | ✅ 自动转换 |
| SpEL 表达式 | ❌ 不支持 | ✅ 支持 |
| 元数据支持 | ✅ 支持(IDE提示) | ❌ 不支持 |
| 批量配置 | ✅ 适合 | ❌ 逐个配置 |
| 验证支持 | ✅ 支持 JSR-303 | ❌ 不支持 |
最佳实践:优先使用
@ConfigurationProperties,仅在需要 SpEL 时使用@Value
五、多环境配置
1. 配置文件命名规范
application.yml # 通用配置
application-dev.yml # 开发环境
application-test.yml # 测试环境
application-prod.yml # 生产环境2. 激活指定环境
方式一:配置文件中指定(推荐开发环境)
# application.yml
spring:
profiles:
active: dev # 默认使用开发环境方式二:命令行参数(推荐生产环境)
java -jar app.jar --spring.profiles.active=prod方式三:环境变量
export SPRING_PROFILES_ACTIVE=prod
java -jar app.jar3. 单文件多环境配置(YAML)
# application.yml
spring:
config:
activate:
on-profile: dev
server:
port: 8080
# 开发环境特有配置
servlet:
context-path: /dev
---
spring:
config:
activate:
on-profile: prod
server:
port: 80
# 生产环境特有配置
servlet:
context-path: /4. 多环境最佳实践
- 通用配置:放在
application.yml - 环境特定配置:放在
application-{env}.yml - 敏感信息:通过环境变量或配置中心提供
- 默认环境:在
application.yml中设置spring.profiles.active=dev
六、实用配置技巧
1. 随机值生成
my:
secret: ${random.value}
number: ${random.int}
test1: ${random.int(10)} # 0-9 的随机整数
test2: ${random.int[10,20]} # 10-20 的随机整数
uuid: ${random.uuid}应用场景:
- 生成临时密钥
- 避免端口冲突(
server.port=${random.int[8081,8090]}) - 创建唯一标识
2. 参数引用
book:
name: Spring Boot
author: John Doe
desc: "${book.author} is writing《${book.name}》"
# 跨配置引用
server:
port: 8080
url: http://localhost:${server.port}3. 命令行覆盖配置
# 覆盖单个配置
java -jar app.jar --server.port=9090
# 覆盖多个配置
java -jar app.jar --server.port=9090 --spring.datasource.password=secret
# 指定配置文件
java -jar app.jar --spring.config.location=classpath:/custom-config.yml4. 条件化配置
@Configuration
@ConditionalOnProperty(name = "cache.enabled", havingValue = "true")
public class CacheConfig {
// 仅当 cache.enabled=true 时加载此配置
}七、敏感信息安全处理
1. 基本安全实践
- 不要将敏感信息提交到代码仓库
- 使用环境变量存储敏感信息
- 使用配置中心管理敏感信息
# application.yml
spring:
datasource:
password: ${DB_PASSWORD} # 从环境变量读取设置环境变量:
export DB_PASSWORD="mysecretpassword"
java -jar app.jar2. 使用 Jasypt 加密配置(推荐)
步骤 1:添加依赖
<dependency>
<groupId>com.github.ulisesbocchio</groupId>
<artifactId>jasypt-spring-boot-starter</artifactId>
<version>3.0.5</version>
</dependency>步骤 2:配置加密密钥
# application.yml
jasypt:
encryptor:
password: my-strong-password # 加密密钥(应通过环境变量提供)步骤 3:使用加密值
spring:
datasource:
password: ENC(cipher-text-here)加密工具命令:
# 加密文本
java -cp app.jar com.ulisesbocchio.jasypt.springboot.cli.JasyptSpringCLI \
application.yml my-strong-password encrypt "my-secret-password"
# 解密文本(调试用)
java -cp app.jar com.ulisesbocchio.jasypt.springboot.cli.JasyptSpringCLI \
application.yml my-strong-password decrypt "ENC(cipher-text-here)"最佳实践:
- 将
jasypt.encryptor.password通过环境变量提供 - 开发环境使用简单密码,生产环境使用强密码
- 定期轮换加密密钥
八、配置加载原理
1. 配置加载流程
- Spring Boot 启动时扫描所有配置源
- 按优先级合并配置
- 将配置绑定到
Environment对象 - 通过
@Value或@ConfigurationProperties注入
2. 自定义配置加载
@Configuration
@PropertySource("classpath:custom.properties")
public class CustomConfig {
@Value("${custom.property}")
private String customProperty;
// ...
}注意:
@PropertySource默认不支持 YAML,仅支持 Properties 格式
九、常见问题与解决方案
1. 配置不生效?
- 检查配置项名称是否正确(使用松散绑定规则)
- 检查配置文件位置是否正确
- 检查配置优先级(是否有更高优先级配置覆盖)
- 添加
@RefreshScope(如果使用 Spring Cloud Config)
2. 如何查看所有生效配置?
访问 Actuator 端点:
http://localhost:8080/actuator/env需要添加依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>3. 配置热更新
@Component
@RefreshScope // 标记需要刷新的Bean
@ConfigurationProperties(prefix = "app.config")
public class AppConfig {
private String someProperty;
// ...
}当配置中心配置变化时,调用:
POST /actuator/refresh4. 配置验证
@Component
@ConfigurationProperties(prefix = "app")
@Validated
public class AppConfig {
@NotBlank
private String name;
@Min(1)
@Max(100)
private int maxThreads;
// ...
}添加验证依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>十、最佳实践总结
- 优先使用 YAML:层次清晰,配置简洁
- 配置与代码分离:不要将配置硬编码在代码中
- 使用 @ConfigurationProperties:类型安全,易于维护
- 多环境配置:
application-{env}.yml模式 - 敏感信息保护:环境变量或加密存储
- 合理使用随机值:避免端口冲突等问题
- 配置验证:确保关键配置的正确性
- 不要提交敏感信息:.gitignore 中包含配置文件
