跳到主要内容

配置管理

问题

Spring Boot 的配置文件有哪些?配置的优先级是什么?如何实现多环境配置?

答案

配置文件类型

类型文件名特点
Propertiesapplication.propertieskey=value 格式,简单直接
YAMLapplication.yml层级结构,可读性强
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)

application.yml — 公共配置
spring:
profiles:
active: dev # 默认激活 dev 环境
application-dev.yml — 开发环境
server:
port: 8080
spring:
datasource:
url: jdbc:mysql://localhost:3306/mydb
logging:
level:
root: DEBUG
application-prod.yml — 生产环境
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 对象:

MyAppProperties.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...
}
application.yml
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)不应明文存储:

使用 jasypt 加密
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: 配置文件中的敏感信息如何处理?

答案

常见方案:

  1. 环境变量:通过 ${DB_PASSWORD} 引用系统环境变量
  2. 配置中心:使用 Nacos/Apollo 等配置中心管理,支持加密和动态刷新
  3. Jasypt 加密:在配置文件中使用 ENC(密文),运行时自动解密
  4. Vault:使用 HashiCorp Vault 等密钥管理服务

Q5: 松散绑定(Relaxed Binding)是什么?

答案

@ConfigurationProperties 支持多种属性名风格自动匹配:

配置文件写法Java 属性名
my.app.max-retrymaxRetry(推荐用短横线分隔
my.app.maxRetrymaxRetry
my.app.MAX_RETRYmaxRetry(环境变量风格)
my.app.max_retrymaxRetry

相关链接