1. YAML 文件结构和语法
缩进与层次
YAML使用缩进来表示层级关系。每个层级的元素必须比它的父级多一个空格或Tab(推荐使用空格)。例如:
server:
port: 8080
address: localhost
列表与映射
列表用 -
开头,映射则用 key: value
形式。可以混合使用。
myapp:
features:
- featureA
- featureB
settings:
timeout: 30s
maxConnections: 50
多行字符串
对于较长的字符串,可以使用 |
或 >
来表示多行文本。|
会保留换行符,而>
会将多行合并为一行并去掉多余的空白。
message: |
这是一个多行字符串。
它保留了换行符。
message2: >
这也是一个多行字符串。
但它的换行符被忽略了。
使用锚点和别名避免重复
为了减少冗余,YAML允许使用锚点(&
)和别名(*
)来引用之前定义的内容。
defaults: &defaults
timeout: 30s
retries: 3
service1:
<<: *defaults
url: http://service1.example.com
service2:
<<: *defaults
url: http://service2.example.com
这里,<<: *defaults
表示将 defaults
中的所有属性合并到当前节点中。
2. 多环境配置
激活特定配置文件
你可以通过命令行参数、系统属性或在代码中设置激活的配置文件。
- 命令行:
java -jar app.jar --spring.profiles.active=dev
- 系统属性:
-Dspring.profiles.active=dev
- 应用程序内:
spring.profiles.active=dev
组合配置文件
如果你有多个配置文件,比如 application.yml
和 application-dev.yml
,后者会覆盖前者中的相同配置项。
3. 属性占位符和默认值
占位符引用
可以使用 ${}
语法来引用其他属性或环境变量,并可设置默认值。
database:
url: jdbc:mysql://${DB_HOST:localhost}:${DB_PORT:3306}/dbname
动态表达式
除了静态替换外,还可以使用 Spring Expression Language (SpEL) 来动态计算值。
maxThreads: '#{T(java.lang.Runtime).getRuntime().availableProcessors() * 2}'
4. 配置类与 @ConfigurationProperties
自定义配置类
创建一个POJO类用于接收配置项,并使用 @ConfigurationProperties
注解绑定到这个类。
@ConfigurationProperties(prefix = "myapp")
public class MyAppProperties {
private String name;
private List<String> admins = new ArrayList<>();
// getters and setters
}
验证配置
为了确保配置的有效性,可以在配置类上添加JSR-303/Bean Validation注解。
@ConfigurationProperties(prefix = "myapp")
public class MyAppProperties {
@NotNull
private String name;
@Size(min = 1)
private List<String> admins = new ArrayList<>();
// getters and setters
}
5. 使用 @Value 注解注入配置
简单注入
直接使用 @Value
注入简单的配置项。
@Component
public class MyComponent {
private final String apiKey;
public MyComponent(@Value("${myapp.api-key}") String apiKey) {
this.apiKey = apiKey;
}
}
结合 SpEL 使用
@Value
支持 SpEL 表达式,允许进行更复杂的逻辑操作。
@Value("#{${myapp.timeout} * 1000}")
private int timeoutInMillis;
SpEL不仅限于简单的数学运算,还可以执行条件判断、调用方法等复杂操作。例如:
@Value("#{T(java.lang.Math).random() > 0.5 ? 'high' : 'low'}")
private String randomLevel;
引用其他bean的方法
你可以在表达式中直接引用其他bean的方法:
@Component
public class UtilityService {
public String generateToken() {
return UUID.randomUUID().toString();
}
}
@Component
public class MyComponent {
@Value("#{@utilityService.generateToken()}")
private String token;
}
6. 加密敏感信息
Jasypt
Jasypt 是一个流行的库,用于加密 Spring Boot 应用程序中的敏感数据。你可以在 pom.xml
中添加依赖,并使用它来加密配置项。
<dependency>
<groupId>com.github.ulisesbocchio</groupId>
<artifactId>jasypt-spring-boot-starter</artifactId>
<version>3.0.3</version>
</dependency>
然后,在配置文件中使用 {cipher}
标签来标记加密过的值。
myapp:
secret: ENC(encrypted_value)
要解密这些值,你需要设置 jasypt.encryptor.password
属性来指定加密密码。
jasypt:
encryptor:
password: my_secret_password
除了前面提到的基本用法,Jasypt还支持多种加密算法以及密钥管理策略。你可以通过配置 jasypt.encryptor.*
属性来自定义加密行为。
jasypt:
encryptor:
algorithm: PBEWithMD5AndDES
password: my_secret_password
iv-generator-classname: org.jasypt.iv.NoIvGenerator
此外,Jasypt也提供了对非对称加密的支持,如RSA。
7. 使用外部化配置
优先级顺序
Spring Boot 按照一定的顺序加载配置源,从命令行参数到默认配置文件。了解这些来源的加载顺序有助于正确地管理和覆盖配置。
- 命令行参数
- 来自
SPRING_APPLICATION_JSON
的属性(嵌入在环境变量或系统属性中) - 操作系统的环境变量
- Java 系统属性 (
System.getProperties()
) RandomValuePropertySource
配置的随机属性 (random.*
)- 打包在 jar 包外的应用配置文件 (
application-{profile}.properties
或.yml
) - 打包在 jar 包内的应用配置文件 (
application-{profile}.properties
或.yml
) - 配置文件(如
bootstrap.properties
或bootstrap.yml
),适用于微服务架构中的配置服务器 - 默认属性(通过
SpringApplication.setDefaultProperties
指定)
8. 高级特性
条件化配置
使用 @ConditionalOnProperty
注解可以根据配置属性的存在与否来有条件地加载bean。
@Bean
@ConditionalOnProperty(name = "myapp.enabled", havingValue = "true")
public MyService myService() {
return new MyServiceImpl();
}
除了 @ConditionalOnProperty
,还有其他条件注解,如 @ConditionalOnClass
, @ConditionalOnMissingBean
等,可以根据类路径上的类、是否存在某些bean等条件来决定是否加载配置。
@Bean
@ConditionalOnClass(name = "com.example.MyLibraryClass")
public MyService myService() {
return new MyServiceImpl();
}
使用 EnvironmentPostProcessor
扩展配置处理
为了在应用程序启动前修改环境变量,你可以实现 EnvironmentPostProcessor
接口。例如,根据系统属性动态调整配置文件的位置:
public class CustomEnvironmentPostProcessor implements EnvironmentPostProcessor {
@Override
public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
String customConfigLocation = System.getProperty("custom.config.location");
if (customConfigLocation != null) {
environment.getPropertySources().addFirst(new ResourcePropertySource(customConfigLocation));
}
}
}
然后注册这个处理器:
spring.application.additional-spring-configuration-metadata=classpath:META-INF/spring-configuration-metadata.json
并且在 META-INF/spring.factories
中声明:
org.springframework.boot.env.EnvironmentPostProcessor=com.example.CustomEnvironmentPostProcessor
配置元数据支持
为了提高开发体验,Spring Boot 提供了对配置元数据的支持,使得IDE能够更好地理解你的配置选项,并提供自动完成等功能。这需要在项目中包含 spring-boot-configuration-processor
依赖。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>