Spring Boot外部配置
外部配置(Externalized Configuration)
来源于spring boot官方文档的简单笔记,写的比较乱,大体上是作为简单的梳理,回过头来看的,或者快速查找目录使用,详细的还是要看官方文档
配置属性读取顺序为:
- devtools global settings properties,位置~/.spring-boot-devtools.properties
- @TestPropertySource
- 测试的properties属性,包含@SpringBootTest和其他的测试注解
- 命令行参数(command line argument)
- SPRING_APPLICATION_JSON获取的属性
- ServletConfig初始化参数
- ServletContext初始化参数
- JNDI属性,从java:comp/dev
- java系统属性(System.getProperties())
- 系统环境变量
- RandomValuePropertySource中random.*的值
- jar包外指定的应用属性,application-{profile}.properties以及YAML变量
- jar包内的指定的应用属性,application-{profile}.properties以及YAML变量
- jar包外的application.properties配置或者YAML
- jar包内的application.properties
- 在@Configuration注解类上配置的@PropertySource注解配置
- 默认属性(通过SpringApplication.setDefaultProperties)
配置随机值(Configuring Random Values)
RandomValuePropertySource对于属性设置随机值非常方便,包含了integers,longs,uuid,strings等等随机值
my.secret=${random.value}
my.number=${random.int}
my.bignumber=${random.long}
my.uuid=${random.uuid}
my.number.less.than.ten=${random.int(10)}
my.number.in.range=${random.int[1024,65536]}
其中对于int或者long等(是开口,不包含,[包含。
获取命令行属性(Accessing Command Line Properties)
在命令行启动时,可以通过使用--
前缀标志属性,比如--server.port=9000
,可以添加到spring的environment中,可以通过SpringApplication.setAddCommandLineProperties(false)禁用。
应用属性文件(Application Property Files)
SpringApplication从以下顺序位置读取application.properties文件中的属性到Spring Environment:
- 当前目录的/config
- 当前目录
- classpath下面的/config包
- classpath的根路径
当然了,也是可以支持YAML(.yml)文件。
如果不想使用application.properties名字,可以通过使用spring.config.name指定文件名,通过spring.config.location指定读取的路径(多个路径使用逗号隔开)。
如果路径中包含目录的话,注意需要/结尾,通过这个路径直接拼接上name指定的名字。
注意,配置路径的搜索顺序是反着来的,也就是说,如果配置了多个路径的话后面的路径的排在前面优先级。
也可以通过spring.config.additional-location配置的搜索路径,在默认路径之前搜索。
指定环境属性(Profile-specific Properties)
除了application.properties文件,还有可以指定环境属性配置文件,约定的规则是:application-{profile}.properties。默认的是default,也就是说没有指定的话就是导入application-default.properties。该文件如果有的话,会优先于application.properties配置。
对于指定了多个spring.profiles.active,以最后一个生效。
注意:spring.config.location指定了,那么直接在该位置搜索配置,profile-specific变量就不会考虑了。
属性占位符(Placeholders in Properties)
application.properties文件中的属性使用时会通过Environment中存在的值过滤,也就是说,反过来,配置文件中的属性值可以使用Environment中的属性。
app.name=App
app.description=${app.name} is a Spring Boot application
加密属性(Encrypting Properties)
Spring Boot对于加密属性值没有提供内建的支持,但是对于修改Environment中的属性值提供了钩子(hook),EnvironmentPostProcessor接口可以操作属性中的值,也就是说Evironment中的属性加载完成以后会先执行EnvironmentPostProcessor接口中的方法,然后再启动应用。
对于Spring Cloud Vault中有相关的处理,有兴趣可以查看一下。
使用YAML代替属性(Using YAML Instead of Properties)
YAML是JSON格式的超类,结构化的样式配置数据。对于YAML格式简单点说就是一般以.yml结尾的配置文件,通过缩进的方式配置属性。SpringApplication是自动支持YAML的,在spring-boot-starter中是包含了SnakeYAML库的。
Spring框架有YamlPropertiesFactoryBean读取YAML为Properties,YamlMapFactoryBean导入YAML为一个Map。
environments:
dev:
url: https://dev.example.com
name: Developer Setup
prod:
url: https://another.example.com
name: My Cool App
等效于:
environments.dev.url=https://dev.example.com
environments.dev.name=Developer Setup
environments.prod.url=https://another.example.com
environments.prod.name=My Cool App
对于数组类型的:
my:
servers:
- dev.example.com
- another.example.com
//等效于
my.servers[0]=dev.example.com
my.servers[1]=another.example.com
对于数据的绑定,数组的话可以使用List或者Set,需要提供一个setter方法或者初始化为一个可变的值。可以通过@ConfigurationProperties注解自动注入。
@ConfigurationProperties(prefix="my")
public class Config {
private List<String> servers = new ArrayList<String>();
public List<String> getServers() {
return this.servers;
}
}
可以通过YamlPropertySourceLoader将YAML文件作为PropertySource到Spring的Environment中。这样的话可以使用@Value作为占位符语法。
多环境YAML文档(Multi-profile YAML Documents)
在YAML当个文档中,可以通过spring.profiles键来标志配置的**环境:
server:
address: 192.168.1.100
---
spring:
profiles: development
server:
address: 127.0.0.1
---
spring:
profiles: production & eu-central # 此处是表达式语法
server:
address: 192.168.1.120
如上示例所示,没有指定profiles的为默认状态。
类型安全的配置属性(Type-safe Configuration Properties)
使用@Value("${property}")注入属性值,遇到需要注入的变量太多的时候,就比较繁琐,这个使用SpringBoot提供@ConfigurationProperties注解快速注入属性,上一小节也有使用示例。通过@ConfigurationProperties(prefix="")的方式之前前缀,然后就会自动将环境中这种对象的前缀加上变量拼接的属性中匹配,找到的话就将值设置到使用该注解的对象中。
注意:Getters和Setters通常是必要的,因为属性自动绑定是通过标准的java bean属性描述,和Spring MVC相似。在以下场景中,可以不需要setter:
- Maps,只要初始化以后,需要getter方法,不需要setter了,因为可以被绑定器修改(can be mutated by the binder)。
- Collections以及数组可以通过索引(典型的是YAML)或者通过单个中间使用逗号隔开的值注入。后者setter方法是必须的,我们建议是最好都加上setter方法。如果集合初始化了,确保是可变的。
- 对于内部的一个初始化了的POJO属性,不需要setter。如果你想使用默认构造器创建实例,需要setter方法(if you want to the binder to create the instance on the fly by using its default constructor,you need a setter)。
- 有些人使用Lombok自动添加getters以及setters,确保Lombok对于这些类型不生成特别的构造器,因为容器会自动使用这些构造器初始化对象。
- 最后,该方式只支持标准java bean属性,绑定到静态属性中是不支持的。
对于触发该注解的方式有两种,一种是在配置类中使用@EnableConfigurationProperties(AcmeProperties.class),标明AcmeProperties类需要自动注入属性,也可以直接标明需要注入类为Spring的一个组件,比如@Component,@Bean之类的。
@Configuration
@EnableConfigurationProperties(AcmeProperties.class)
public class MyConfiguration {
}
@Component
@ConfigurationProperties(prefix="acme")
public class AcmeProperties {
// ... see the preceding example
}
@ConfigurationProperties(prefix = "another")
@Bean
public AnotherComponent anotherComponent() {
...
}
对于属性前缀这种自动配置方式,spring提供了更加宽松话的匹配规则,比如说大小写差别,驼峰,中间加-等标记,具体可以到文档中查看,针对.properties,.yml,environment,系统属性等等,有一点点差别。但是如果不是特殊情况还是不建议差别太大。
在属性自动装配时,spring会自动往正确的类型转换,如果需要自定义的话,可以提供ConversionService或者定制属性编辑器(通过CustomEditorConfigurer对象)或者定制转换器Converters(使用@ConfigurationPropertiesBinding注解标注)
对于自动转换的属性变量,可以使用注解指定单位之类的,比如@DurationUnit(ChronoUnit.SECONDS),@DataSizeUnit(DataUnit.MEGABYTES)等等。
也可以使用@Validated注解使用验证格式,该注解遵循的是JSR-303
@ConfigurationProperties 和 @Value的区别
其中前一个支持宽松绑定(Relaxed binding)以及元数据支持(Meta-data support),后者支持SpEL表达式。
推荐阅读
-
Spring Boot 配置元数据指南
-
Spring Boot → 07:错误处理机制
-
三、解决Spring MVC拦截器导致静态资源访问失败(基于java注解配置)
-
spring boot踩坑记
-
spring boot从redis取缓存发生java.lang.ClassCastException异常
-
spring-boot-2.0.3不一样系列之源码篇 - run方法(三)之createApplicationContext,绝对有值得你看的地方
-
Spring Boot @Scheduled定时任务代码实例解析
-
Spring MVC五大核心组件和配置
-
Spring Boot认证:整合Jwt
-
Spring+Spring MVC+Mybatis 框架整合开发(半注解半配置文件)