Spring Boot外部配置

外部配置(Externalized Configuration)

来源于spring boot官方文档的简单笔记,写的比较乱,大体上是作为简单的梳理,回过头来看的,或者快速查找目录使用,详细的还是要看官方文档

配置属性读取顺序为:

  1. devtools global settings properties,位置~/.spring-boot-devtools.properties
  2. @TestPropertySource
  3. 测试的properties属性,包含@SpringBootTest和其他的测试注解
  4. 命令行参数(command line argument)
  5. SPRING_APPLICATION_JSON获取的属性
  6. ServletConfig初始化参数
  7. ServletContext初始化参数
  8. JNDI属性,从java:comp/dev
  9. java系统属性(System.getProperties())
  10. 系统环境变量
  11. RandomValuePropertySource中random.*的值
  12. jar包外指定的应用属性,application-{profile}.properties以及YAML变量
  13. jar包内的指定的应用属性,application-{profile}.properties以及YAML变量
  14. jar包外的application.properties配置或者YAML
  15. jar包内的application.properties
  16. 在@Configuration注解类上配置的@PropertySource注解配置
  17. 默认属性(通过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表达式。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章