baeldung 2020-08-22
1. 概述
在 Spring Boot 中,一种常见的做法是使用外部配置来定义属性。这使我们能够在不同环境中使用相同的代码。
我们可以使用属性文件(properties)、YAML 文件、环境变量和命令行参数进行配置。
在本简短教程中,我们将探讨 properties 文件和 YAML 文件之间的主要区别。
2. Properties 配置
默认情况下,Spring Boot 可以读取 application.properties 文件中的配置,该文件采用键值对格式:
spring.datasource.url=jdbc:h2:dev
spring.datasource.username=SA
spring.datasource.password=password
每一行代表一个独立的配置项,因此我们需要通过为键添加相同的前缀来表达层次结构数据。在上面的例子中,所有键都属于 spring.datasource 命名空间。
2.1. Properties 中的占位符
在属性值中,我们可以使用 ${} 语法引用其他键、系统属性或环境变量的内容:
app.name=MyApp
app.description=${app.name} is a Spring Boot application
2.2. 列表结构
如果存在多个具有相同类型但不同值的属性,可以使用数组索引表示列表结构:
application.servers[0].ip=127.0.0.1
application.servers[0].path=/path1
application.servers[1].ip=127.0.0.2
application.servers[1].path=/path2
application.servers[2].ip=127.0.0.3
application.servers[2].path=/path3
2.3. 多文档 Profiles(多环境配置)
从 Spring Boot 2.4.0 版本开始,支持在单个 properties 文件中使用“多文档”格式。简单来说,我们可以将一个物理文件划分为多个逻辑文档。
这样,我们可以在同一个文件中为每个需要声明的 profile 定义独立的配置段:
logging.file.name=myapplication.log
bael.property=defaultValue
#---
spring.config.activate.on-profile=dev
spring.datasource.password=password
spring.datasource.url=jdbc:h2:dev
spring.datasource.username=SA
bael.property=devValue
#---
spring.config.activate.on-profile=prod
spring.datasource.password=password
spring.datasource.url=jdbc:h2:prod
spring.datasource.username=prodUser
bael.property=prodValue
注意:我们使用 #--- 标记来指示新文档的开始。
在此示例中,我们有两个带有不同 profile 标签的配置段。此外,还可以在根级别定义通用属性 —— 例如,logging.file.name 属性在所有 profile 中都保持一致。
2.4. 多文件 Profiles
除了将不同 profile 放在同一个文件中外,我们也可以将它们分别存储在不同的文件中。在 Spring Boot 2.4.0 之前,这是 properties 文件唯一支持的方式。
实现方法是在文件名中包含 profile 名称,例如:application-dev.yml 或 application-dev.properties。
3. YAML 配置
3.1. YAML 格式
除了 Java 的 properties 文件,我们还可以在 Spring Boot 应用中使用基于 YAML 的配置文件。YAML 是一种用于指定层次化配置数据的便捷格式。
现在,让我们将前面 properties 文件中的示例转换为 YAML 格式:
spring:
datasource:
password: password
url: jdbc:h2:dev
username: SA
相比 properties 文件,YAML 更具可读性,因为它避免了重复的前缀。
3.2. 列表结构
YAML 提供了更简洁的列表表达方式:
application:
servers:
- ip: '127.0.0.1'
path: '/path1'
- ip: '127.0.0.2'
path: '/path2'
- ip: '127.0.0.3'
path: '/path3'
3.3. 多 Profile 配置
与 properties 文件不同,YAML 本身就支持多文档格式,因此无论使用哪个版本的 Spring Boot,我们都可以在同一个 YAML 文件中存储多个 profile。
在这种情况下,YAML 规范要求使用三个连字符(---)来标记新文档的开始:
logging:
file:
name: myapplication.log
---
spring:
config:
activate:
on-profile: staging
datasource:
password: 'password'
url: jdbc:h2:staging
username: SA
bael:
property: stagingValue
注意:通常我们不建议在项目中同时包含标准的
application.properties和application.yml文件,因为这可能导致意外的结果。
例如,如果我们同时使用上述 YAML 文件(application.yml)和第 2.3 节中描述的 properties 配置,那么 bael.property 将被赋值为 defaultValue,而不是 profile 特定的值。这是因为 application.properties 文件加载时间晚于 application.yml,会覆盖之前设置的值。
4. Spring Boot 中的使用方式
定义好配置后,我们来看看如何在代码中访问这些配置值。
4.1. 使用 @Value 注解
我们可以使用 @Value 注解注入属性值:
@Value("${key.something}")
private String injectedProperty;
这里,属性 key.something 通过字段注入的方式注入到我们的对象中。
4.2. 使用 Environment 抽象
也可以通过 Environment API 获取属性值:
@Autowired
private Environment env;
public String getSomeKey() {
return env.getProperty("key.something");
}
4.3. 使用 @ConfigurationProperties 注解
最后,我们还可以使用 @ConfigurationProperties 注解将属性绑定到类型安全的结构化对象中:
@ConfigurationProperties(prefix = "mail")
public class ConfigProperties {
private String name;
private String description;
// ...
}
5. 结论
在本文中,我们探讨了 Spring Boot 中 properties 与 YAML 配置文件之间的一些关键区别。我们还了解了它们的值如何相互引用,并学习了如何将这些值注入到运行时环境中。