欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Spring Boot外部配置

程序员文章站 2022-04-06 18:48:31
...

外部配置(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表达式。