Spring Boot 中的 YAML 完全指南
一、YAML 是什么?
YAML 是一种人类可读的数据序列化格式,全称是 "YAML Ain't Markup Language"。它比 properties 和 XML 更适合作为配置文件,因为它使用缩进表示层级关系,结构更清晰,表达力更强,而且支持更丰富的数据类型。
Spring Boot 默认支持 YAML 格式的配置文件,文件名通常是 application.yml。它的设计理念是让配置文件既容易阅读也容易编写,尤其适合现代微服务应用中复杂的配置场景。
二、YAML 基础语法
YAML 的基本结构是 key-value 对,用 : 分隔键和值。冒号后面必须有一个空格,这是 YAML 的硬性语法要求。
2.1 键值对
yaml
name: myapp
port: 8080
enabled: true
这对应 properties 写法:
properties
name=myapp
port=8080
enabled=true
2.2 层级结构
YAML 使用缩进表示层级关系,缩进必须使用空格(不能使用 Tab),建议统一使用 2 个空格。相同层级的元素必须左对齐。
yaml
server:
port: 8080
context-path: /api
tomcat:
max-threads: 200
uri-encoding: UTF-8
对应 properties:
properties
server.port=8080
server.context-path=/api
server.tomcat.max-threads=200
server.tomcat.uri-encoding=UTF-8
2.3 注释
使用 # 表示注释:
yaml
# 服务器配置
server:
port: 8080 # 启动端口
2.4 字符串值
字符串通常不需要加引号,但如果包含特殊字符(如 :、#、%、\n、{、}等),需要用单引号或双引号包裹。
yaml
# 普通字符串
name: myapp
description: This is my application
# 需要引号的字符串
message: 'Hello: World' # 包含冒号
path: 'C:\Users\admin' # 包含反斜杠
单引号和双引号的区别:
- 单引号:原样输出,不转义特殊字符
- 双引号:支持转义,可以使用
\n、\t等
yaml
single: 'Hello \n World' # 输出:Hello \n World
double: "Hello \n World" # 输出:Hello (换行) World
2.5 配置重复项
在 YAML 中,重复的键会导致后面的值覆盖前面的值。Spring Boot 不会报错,但会有日志警告。因此编写配置时要保证键的唯一性。
三、YAML 支持的数据类型
3.1 基本类型
yaml
string-value: Hello
integer-value: 100
float-value: 3.14
boolean-value: true
null-value: null # 或 ~
3.2 列表/数组
方式一:- 列表项
yaml
servers:
- server1.example.com
- server2.example.com
- server3.example.com
方式二:内联写法
yaml
servers: [server1.example.com, server2.example.com, server3.example.com]
对应 Java:
java
@Value("${servers}")
private List<String> servers;
3.3 Map / 对象
yaml
features:
cache: true
logging: false
audit: true
对应 Java:
java
@Value("#{${features}}")
private Map<String, Boolean> features;
或者使用 @ConfigurationProperties:
java
@Component
@ConfigurationProperties(prefix = "features")
public class FeaturesProperties {
private boolean cache;
private boolean logging;
private boolean audit;
}
3.4 对象列表
yaml
users:
- name: zhangsan
age: 25
email: zhangsan@example.com
- name: lisi
age: 30
email: lisi@example.com
对应 Java:
java
@Component
@ConfigurationProperties(prefix = "users")
public class UserProperties {
private List<User> users;
@Data
public static class User {
private String name;
private int age;
private String email;
}
}
3.5 复杂嵌套
yaml
database:
primary:
url: jdbc:mysql://localhost:3306/main
username: root
password: 123456
pool:
max-active: 20
min-idle: 5
secondary:
url: jdbc:mysql://localhost:3306/backup
username: backup
password: 654321
pool:
max-active: 10
min-idle: 2
四、Spring Boot 对 YAML 的增强
4.1 多文档块(Profile 支持)
YAML 支持在一个文件中使用 --- 分隔多个文档块,每个文档块可以定义不同的 Profile 配置。
yaml
# 默认配置(第一个文档块)
server:
port: 8080
---
# 开发环境配置
spring:
config:
activate:
on-profile: dev
server:
port: 8080
logging:
level:
root: DEBUG
---
# 生产环境配置
spring:
config:
activate:
on-profile: prod
server:
port: 80
logging:
level:
root: WARN
上面的配置定义了三个文档块:默认配置、开发环境配置(Profile dev 生效)、生产环境配置(Profile prod 生效)。当激活 dev Profile 时,默认配置中的 server.port 会被 dev 块覆盖。
4.2 占位符引用
yaml
app:
name: myapp
version: 1.0
description: ${app.name} - ${app.version}
4.3 属性引用
yaml
spring:
datasource:
url: jdbc:mysql://localhost:3306/mydb
username: root
password: ${spring.datasource.username}_123 # 引用自身
4.4 默认值和随机值
yaml
app:
timeout: ${TIMEOUT:30}
secret: ${random.value}
uuid: ${random.uuid}
五、YAML 与 properties 对比
| 维度 | YAML | properties |
|---|---|---|
| 可读性 | 树形结构,清晰易读 | 扁平结构,重复前缀多 |
| 层级表达 | 通过缩进 | 通过 . 分隔 |
| 列表支持 | 原生支持(- 列表项) |
使用 [0] 索引或逗号分隔 |
| Map 支持 | 原生支持(缩进层级) | 支持,但层级深时难以阅读 |
| 多文档支持 | 支持 --- 分隔 |
需要多个文件 |
| 注释支持 | # |
# |
| 字符串转义 | 支持 \n、\t 等 |
不支持 |
| 类型推断 | 根据值自动推断类型 | 全部是字符串 |
| 与 Spring Boot 兼容性 | 完全兼容 | 完全兼容 |
| 适用场景 | 复杂层级配置 | 简单配置 |
六、常见问题与避坑指南
6.1 缩进问题
YAML 对缩进非常敏感,缩进不正确会导致配置解析失败或行为异常。
yaml
# 错误:缩进不一致
server:
port: 8080 # 4 个空格
context-path: /api # 2 个空格,层级错乱
# 正确:相同层级对齐
server:
port: 8080
context-path: /api
6.2 Tab 与空格
YAML 不允许使用 Tab 缩进,必须使用空格。IDEA 默认将 Tab 转换为空格,通常不会出问题。如果从其他地方复制配置,需要检查缩进字符。
6.3 列表与 Map 的解析陷阱
yaml
features:
cache: true
logging: false
如果使用 @Value 注入 Map,必须使用 SpEL:
java
@Value("#{${features}}")
private Map<String, Boolean> features;
如果使用 @ConfigurationProperties,可以直接绑定。
6.4 配置覆盖行为
在 Spring Boot 中,多个 application-{profile}.yml 文件共存时,后加载的 profile 配置会覆盖前面的。同一个文件中的重复键也会被覆盖(后面的覆盖前面的)。
6.5 对象列表的索引陷阱
使用 properties 格式定义对象列表时,必须用数字索引。而 YAML 中可以用 - 列表项,更直观。
properties
users[0].name=zhangsan
users[0].age=25
users[1].name=lisi
users[1].age=30
七、最佳实践
- 优先使用 YAML 格式,在配置项较多时优势明显
- 保持缩进一致(2 个空格)
- 使用
@ConfigurationProperties绑定复杂配置,而不是用@Value分散注入 - 合理使用 Profile 管理多环境配置,避免在配置文件中硬编码环境信息
- 不要在生产配置中使用
${random.value},这会破坏幂等性 - 敏感信息使用环境变量占位符,避免硬编码在 YAML 中
- 为自定义配置添加
spring-boot-configuration-processor,获得 IDEA 自动补全提示
八、总结
YAML 是 Spring Boot 推荐的配置文件格式,它让配置表达更清晰、更接近人的阅读习惯。缩进表示层级是多层配置的天然表达方式,列表和对象结构比 properties 更容易书写和维护。与 properties 相比,YAML 让配置文件从"扁平键值对"变为"结构化文档",更适合管理大型应用中的复杂配置。当配置层级超过两层或包含列表结构时,YAML 的价值会明显体现出来。无论是小规模应用还是大规模微服务项目,掌握 YAML 的语法和 Spring Boot 对其的增强特性都是必要的技能。