配置管理
Spring Boot 通过统一的 Environment 抽象管理来自不同来源的配置,支持 YAML / Properties 文件、环境变量、命令行参数,并可集成配置中心实现动态刷新。
配置文件格式
YAML vs Properties
两种格式完全等价,推荐使用 YAML(层级清晰,支持列表):
# application.yml
server:
port: 8080
servlet:
context-path: /api
spring:
datasource:
url: jdbc:mysql://localhost:3306/mydb
username: root# application.properties(等价写法)
server.port=8080
server.servlet.context-path=/api
spring.datasource.url=jdbc:mysql://localhost:3306/mydb
spring.datasource.username=rootYAML 支持列表写法:
app:
allowed-origins:
- http://localhost:3000
- https://example.com
# 行内写法也可以
tags: [java, spring, web]配置优先级(从高到低)
命令行参数 --server.port=9090
↓
系统环境变量 SERVER_PORT=9090
↓
JVM 系统属性 -Dserver.port=9090
↓
外部配置文件 ./config/application.yml(jar 包同级)
↓
classpath 配置文件 src/main/resources/application-{profile}.yml
↓
src/main/resources/application.yml
同名属性高优先级覆盖低优先级,命令行参数优先级最高,适合生产部署时临时覆盖。
多环境配置隔离(Profile 机制)详见 环境与Profile。
读取配置的三种方式
1. @Value(简单属性)
@Service
public class AppService {
@Value("${server.port}")
private int port;
@Value("${app.name:未命名}") // 冒号后为默认值
private String appName;
@Value("${app.allowed-origins}")
private List<String> allowedOrigins;
// SpEL 表达式
@Value("#{${app.weights}}") // 解析 Map
private Map<String, Integer> weights;
}
@Value只能注入到 Spring Bean 中,且在构造函数执行之前不可用(构造注入无法用@Value)。
2. @ConfigurationProperties(类型安全,推荐)
将一组相关属性绑定到 POJO,支持嵌套对象、列表、校验:
@ConfigurationProperties(prefix = "app")
@Validated
public class AppProperties {
@NotBlank
private String name;
@Min(1) @Max(65535)
private int port = 8080;
private List<String> allowedOrigins = new ArrayList<>();
private Database database = new Database();
@Data
public static class Database {
private String url;
private int maxPoolSize = 20;
private Duration timeout = Duration.ofSeconds(30);
}
// getters/setters 或 Lombok @Data
}app:
name: 我的应用
port: 8080
allowed-origins:
- http://localhost:3000
database:
url: jdbc:mysql://localhost:3306/mydb
max-pool-size: 20
timeout: 30s # Duration 自动解析注册方式(二选一):
// 方式一:在启动类上扫描
@SpringBootApplication
@ConfigurationPropertiesScan
public class Application {}
// 方式二:在配置类上显式注册
@Configuration
@EnableConfigurationProperties(AppProperties.class)
public class AppConfig {}属性绑定规则(Relaxed Binding):
YAML key → Java 字段
max-pool-size → maxPoolSize (kebab-case → camelCase)
MAX_POOL_SIZE → maxPoolSize (环境变量 UPPER_SNAKE)
maxPoolSize → maxPoolSize (camelCase)
@ConfigurationProperties 的更多细节详见 属性绑定。
3. Environment API(动态读取)
@Service
@RequiredArgsConstructor
public class ConfigService {
private final Environment env;
public String getDbUrl() {
return env.getProperty("spring.datasource.url");
}
public int getPort(int defaultPort) {
return env.getProperty("server.port", Integer.class, defaultPort);
}
public boolean isProd() {
return env.acceptsProfiles(Profiles.of("prod"));
}
}外部化配置
Spring Boot 支持从 jar 包外部读取配置,不重新打包即可修改:
app.jar
config/
application.yml ← 覆盖 jar 内配置
application-prod.yml
或指定任意路径:
java -jar app.jar --spring.config.location=file:/opt/app/config/多路径用逗号分隔(后者优先级更高):
java -jar app.jar \
--spring.config.location=classpath:/,file:/opt/app/config/加密敏感配置
方式一:环境变量(推荐)
不在配置文件中写明文密码,改用占位符从环境变量读取:
spring:
datasource:
password: ${DB_PASSWORD} # 从环境变量读取
data:
redis:
password: ${REDIS_PASSWORD:} # 可选,默认为空export DB_PASSWORD=secret
java -jar app.jarDocker / K8s 中通过 Secret 注入,详见 Docker部署 和 K8s部署。
方式二:Jasypt 加密(配置文件内加密)
implementation 'com.github.ulisesbocchio:jasypt-spring-boot-starter:3.0.5'# 生成密文
java -cp jasypt-3.0.5.jar \
org.jasypt.intf.cli.JasyptPBEStringEncryptionCLI \
input="my-secret-password" password="master-key" algorithm="PBEWithMD5AndDES"
# 输出:ENC(xxxxx)spring:
datasource:
password: ENC(xxxxxabcdef) # jasypt 自动解密
jasypt:
encryptor:
password: ${JASYPT_MASTER_KEY} # 主密钥从环境变量注入配置中心(动态刷新)
Nacos Config
implementation 'com.alibaba.cloud:spring-cloud-starter-alibaba-nacos-config'spring:
config:
import: nacos:application.yml # Spring Boot 3.x 写法
cloud:
nacos:
config:
server-addr: 127.0.0.1:8848
namespace: dev
group: DEFAULT_GROUP
file-extension: yaml
refresh-enabled: true # 开启动态刷新@RestController
@RefreshScope // 标注后,配置变更时 Bean 自动重建
public class ConfigController {
@Value("${feature.enabled:false}")
private boolean featureEnabled;
@GetMapping("/feature")
public boolean isFeatureEnabled() {
return featureEnabled;
}
}Spring Cloud Config Server
# 客户端 bootstrap.yml
spring:
cloud:
config:
uri: http://config-server:8888
label: main
profile: prod配置校验
在 @ConfigurationProperties 类上启用 JSR-303 校验,应用启动时即报错:
@ConfigurationProperties(prefix = "mail")
@Validated
public class MailProperties {
@NotBlank(message = "邮件服务器地址不能为空")
private String host;
@Min(value = 1, message = "端口号最小为 1")
@Max(value = 65535, message = "端口号最大为 65535")
private int port = 25;
@Email(message = "发件人地址格式不正确")
private String from;
@NotNull
private Duration timeout = Duration.ofSeconds(10);
}启动时若配置缺失或格式错误,立即抛出 BindValidationException,快速失败比运行时报错更安全。
参数校验详见 参数校验。
配置文档化(IDE 提示支持)
添加元数据处理器,@ConfigurationProperties 类的属性在 IDE 中自动补全和校验:
annotationProcessor 'org.springframework.boot:spring-boot-configuration-processor'手动补充描述(META-INF/additional-spring-configuration-metadata.json):
{
"properties": [
{
"name": "app.name",
"type": "java.lang.String",
"description": "应用名称,用于日志和监控标识"
}
]
}常见问题
| 问题 | 原因 | 解决方案 |
|---|---|---|
@Value 注入 null | Bean 未被 Spring 管理(如 new 创建) | 确保通过 Spring 注入 |
| Profile 配置不生效 | spring.profiles.active 位置错误 | 放在 application.yml 主文档块 |
| YAML 列表绑定失败 | 环境变量覆盖时格式错误 | 用 VALUE[0]=x,VALUE[1]=y 或 JSON 格式 |
Duration 无法解析 | 格式不对 | 使用 10s、5m、1h 格式 |
| 加密配置解密失败 | 主密钥未注入或算法不匹配 | 检查 jasypt.encryptor.password 环境变量 |