简体中文
Spring Boot 外部化配置详解
什么是外部化配置?
外部化配置是指将应用配置(如数据库连接、端口、日志级别等)从代码中分离出来,放在应用外部(如配置文件、环境变量、命令行参数等),以便在不修改代码的情况下改变应用行为。
Spring Boot 支持多种外部配置来源,按优先级从高到低排列,高优先级的配置会覆盖低优先级的配置。
配置来源与优先级
Spring Boot 的配置加载顺序如下(从高到低):
| 优先级 | 配置来源 | 示例 |
|---|---|---|
| 1 | 命令行参数 | --server.port=8081 |
| 2 | 操作系统环境变量 | SERVER_PORT=8081 |
| 3 | JVM 系统属性 | -Dserver.port=8081 |
| 4 | application.{profile}.properties.yml | application-prod.yml |
| 5 | application.properties.yml | 默认配置文件 |
| 6 | @PropertySource 注解 | 加载自定义配置文件 |
| 7 | 默认值 | 代码中的 @Value 默认值 |
理解这个优先级顺序是排查配置不生效问题的前提。
# 命令行参数最高优先级
java -jar myapp.jar --server.port=8081
# 环境变量(将 . 替换为 _,转为大写)
export SERVER_PORT=8081
java -jar myapp.jar
# JVM 系统属性
java -Dserver.port=8081 -jar myapp.jar2
3
4
5
6
7
8
9
Profile 多环境配置
Profile 是 Spring Boot 多环境管理的基础机制。通过激活不同的 Profile,应用会加载对应的配置文件。
多文件方式
application.yml # 通用配置
application-dev.yml # 开发环境
application-test.yml # 测试环境
application-prod.yml # 生产环境2
3
4
单文件多文档块方式
# 默认配置
spring:
profiles:
active: dev
---
# 开发环境
spring:
config:
activate:
on-profile: dev
server:
port: 8080
---
# 生产环境
spring:
config:
activate:
on-profile: prod
server:
port: 802
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
激活 Profile 的方式
# 命令行激活
java -jar myapp.jar --spring.profiles.active=prod
# 环境变量激活
export SPRING_PROFILES_ACTIVE=prod
# JVM 系统属性激活
java -Dspring.profiles.active=prod -jar myapp.jar2
3
4
5
6
7
8
@Value 与 @ConfigurationProperties
@Value 注入单个配置值
@Service
public class AppConfig {
@Value("${app.name:default-app}")
private String appName;
@Value("${app.timeout:30}")
private int timeout;
@Value("${app.features.enabled:false}")
private boolean featureEnabled;
}2
3
4
5
6
7
8
9
10
11
@Value 支持 SpEL 表达式,但只能注入简单类型。它会在 Spring 容器初始化时处理,如果配置缺失且没有默认值,启动时会抛出异常。
@Value("#{${app.ports} ?: '{8080,8081}'}")
private int[] ports;2
@ConfigurationProperties 批量绑定
@Component
@ConfigurationProperties(prefix = "app")
@Data
public class AppProperties {
private String name;
private int timeout;
private List<String> servers;
private Map<String, String> features;
private Security security = new Security();
@Data
public static class Security {
private boolean enabled;
private String secret;
}
}2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
对应的配置:
app:
name: my-app
timeout: 30
servers:
- server1.example.com
- server2.example.com
features:
cache: true
logging: false
security:
enabled: true
secret: xyz1232
3
4
5
6
7
8
9
10
11
12
@ConfigurationProperties 适合绑定一组相关配置,支持复杂类型(List、Map、嵌套对象),适合批量管理配置项。@Value 适合绑定单个配置值,适合只在少数地方使用的配置。
验证配置
配合 @Validated 进行配置校验:
@Component
@ConfigurationProperties(prefix = "app")
@Validated
@Data
public class AppProperties {
@NotBlank
private String name;
@Min(1)
@Max(60)
private int timeout;
}2
3
4
5
6
7
8
9
10
11
12
配置文件的位置
Spring Boot 会按以下顺序查找 application.yml 或 application.properties:
- 项目根目录下的
config子目录(/config/) - 项目根目录
classpath下的config包(classpath:/config/)classpath根目录
外置配置文件优先级更高,适合生产环境覆盖配置。
# 外置配置文件
/opt/app/config/application.yml
# 默认 classpath 配置文件
src/main/resources/application.yml2
3
4
5
可以显式指定配置文件位置:
java -jar myapp.jar --spring.config.location=/opt/config/application.yml
spring.config.location 会覆盖默认路径,spring.config.additional-location 会在默认路径基础上添加额外路径。2
随机值生成
Spring Boot 支持使用 RandomValuePropertySource 生成随机值:
app:
secret: ${random.value}
uuid: ${random.uuid}
number: ${random.int(100)}
range: ${random.int(10,20)}
long: ${random.long}
@Value("${app.secret}")
private String secret;
@Value("${app.uuid}")
private String uuid;2
3
4
5
6
7
8
9
10
11
自定义配置文件
@PropertySource
加载自定义配置文件:
@Configuration
@PropertySource("classpath:custom.properties")
@PropertySource("file:/opt/config/custom.properties")
public class CustomConfig {
@Value("${custom.value}")
private String customValue;
}2
3
4
5
6
7
自定义 PropertySource
在代码中添加配置来源:
@Component
public class CustomPropertySourceConfig {
@Bean
public PropertySource<?> customPropertySource() {
Map<String, Object> map = new HashMap<>();
map.put("custom.key", "custom-value");
return new MapPropertySource("custom", map);
}
}2
3
4
5
6
7
8
9
类型安全配置提示
为自定义配置类添加元数据,让 IDE 提供自动补全提示:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>2
3
4
5
编译后会生成 META-INF/spring-configuration-metadata.json,IDE 会识别并提供配置提示。
@Component
@ConfigurationProperties(prefix = "app")
public class AppProperties {
/**
* Application name
*/
private String name;
/**
* Connection timeout in seconds
*/
private int timeout = 30;
}2
3
4
5
6
7
8
9
10
11
12
13
敏感信息处理
生产环境中,数据库密码等敏感信息不应硬编码在配置文件中。
使用环境变量
spring:
datasource:
username: ${DB_USERNAME}
password: ${DB_PASSWORD}2
3
4
启动时通过环境变量传入:
export DB_USERNAME=root
export DB_PASSWORD=secret
java -jar myapp.jar2
3
使用加密配置
配合 Spring Cloud Config 或 Jasypt 进行配置加密。
Jasypt 示例:
<dependency>
<groupId>com.github.ulisesbocchio</groupId>
<artifactId>jasypt-spring-boot-starter</artifactId>
<version>3.0.5</version>
</dependency>2
3
4
5
spring:
datasource:
password: ENC(encrypted-password-value)2
3
常见问题排查
配置不生效
检查配置来源的优先级顺序,高优先级的配置会覆盖低优先级。命令行参数 > 环境变量 > JVM 系统属性 > 外部配置文件 > 内部配置文件 > 默认值。
加载顺序确认
在启动类中添加日志打印:
@SpringBootApplication
public class Application {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(Application.class, args);
ConfigurableEnvironment environment = context.getEnvironment();
// 打印所有配置属性
System.out.println(environment.getProperty("app.name"));
}
}2
3
4
5
6
7
8
9
属性来源查看
启用 debug 模式查看配置加载详情:
debug: true或启动时添加 --debug 参数,Spring Boot 会输出条件评估报告,显示每个自动配置类是否生效以及原因。
总结
外部化配置是 Spring Boot 支持多环境部署的基础能力。掌握配置的优先级顺序、Profile 机制和配置绑定方式,就能灵活管理不同环境的配置,保证应用在不同部署环境中正确运行。生产环境中结合环境变量和加密方案管理敏感信息,避免将敏感信息泄露到代码仓库中。
