来一块玩SpringBoot(贰) SpringBoot配置

SpringBoot配置:

SpringBoot有很多种配置的方式,这样方便使代码在不同的运行环境中运行。你可以使用 properties文件YML文件环境变量命令行参数 等方式来配置SpringBoot,属性值可以通过 @Value 注释直接注入到你的bean里也可以通过 Environment 或者 @ConfigurationProperties 去加载到Spring中。

加载顺序

SpringBoot使用一种非常特殊的 PropertySource 顺序加载配置文件,诣在允许合理的覆盖原有的属性值。
下面顺序按照生效顺序排序,谁先最终生效谁排第一!

  1. Devtool
  2. @TestPropertySource (测试属性)
  3. property 属性测试(测试程序中@SpringBootTest 的测试属性)
  4. 命令行参数 (比如java -jar xxx.jar –name=”Spring”)
  5. SPRING_APPLICATION_JSON 的属性
  6. ServletConfig init属性
  7. ServletContext init属性
  8. JNDI属性
  9. JAVA系统属性 (System.getProperty)
  10. OS环境变量
  11. RandomValuePropertySource
  12. 在jar包之外的 application-{profile}.properties/yml
  13. 在jar包内的 application-{profile}.properties/yml
  14. 在jar包之外的application.properties/yml
  15. 在jar包内的 application.properties/yml
  16. @Configuration 注释的属性
  17. 默认属性

比如我们使用Component 定义一个 name 属性

1
2
3
4
5
6
7
8
9
10
11
12
import org.springframework.stereotype.*;
import org.springframework.beans.factory.annotation.*;

@Component
public class MyBean {

@Value("${name}")
private String name;

// ...

}

我们可以用很多种方法去覆盖这个 name ,比如在jar中的 application.properties 定义 name 亦或者在执行jar的时候添加 name

1
java -jar xxx.jar --name="Spring"

Configuring Random Values

RandomValuePropertySource 对于一些需要随机数的场景还是非常有用的,RandomValuePropertySource 可以生成整数、长整数、UUID或者字符串。

1
2
3
4
5
6
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]}

命令行属性

通常情况下SpringApplication能够识别任何命令行参数( --** ,如 --server.port=9090 )的值,并且会将其添加到Spring的 Environment 中,通过上面的配置文件生效顺序可以知道,在运行时,命令行属性的生效优先级是永远高于其它方式的。

配置文件

SpringApplication会从下面几个路径找到application.properties/application.yml并且将其属性值添加到Spring的 Environment

  1. ~/config (项目根目录下的cinfig文件夹下)
  2. ~/ (项目根目录)
  3. classpath/config (classpath下的config)
  4. classpath/

列表按优先级排序(在列表中较高位置定义的属性将覆盖在较低位置中定义的属性)。

如果你不喜欢application这个名字,可以通过修改 spring.config.name 将配置文件的名字切换成你期望的名字。

1
2
#让SpringApplication加载glitterPlayer.properties/glitterPlayer.yml不再加载application.properties/application.yml
java -jar XXX.jar --spring.config.name = glitterPlayer

也可以个更改SpringApplication加载.properties/.yml路径

1
java -jar xxx.jar --spring.config.location = classpath:/default.properties,classpath:/override.properties

如果 spring.config.location 包含的是目录而不是文件,则必须以 / 结尾。如果要指定多个路径或者文件,中间应以 , 隔开,且如果指定了多个路径或者文件,那么这些路径或者文件的生效顺序是从后向前的,比如指定的位置是: classpath:/,classpath:/config/,file:./,file:./config/ 那么对应的生效顺序如下:

  1. file:./config/
  2. file:./
  3. classpath:/config/
  4. classpath:/

使用 spring.config.location 指定目录时,会替换默认目录,比如配置spring.config.location 的值为:
classpath:/custom-config/,file:./custom-config/ ,则配置生效顺序为:

  1. file:./custom-config/
  2. classpath:custom-config/

使用 spring.config.additional-location 的时候,会在原有的目录上增加目录,比如 spring.config.additional-location 的值为 classpath:/custom-config/,file:./custom-config/ 那么配置生效的顺序为:

  1. file:./custom-config/
  2. classpath:custom-config/
  3. file:./config/
  4. file:./
  5. classpath:/config/
  6. classpath:/

_注意:如果使用操作系统变量的方式去配置SpringBoot的属性值,应用大写的写法,比如: SPRING_CONFIG_NAME _

使用YML替换Properties

yml是json的超集使用起来非常方便,SpringBoot官方是非常推崇YML的,我个人也比较喜欢YML的写法。SpringBoot中使用yml语法也非常简单,配置文件以yml(*.yml)结尾的就可以使用yml语法。
对比一下yml和properties

1
2
3
4
5
6
7
8
# yml
environments:
dev:
url: https://dev.example.com
name: Developer Setup
prod:
url: https://another.example.com
name: My Cool App
1
2
3
4
5
# properties
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
yml和properties表示数组
1
2
3
4
my:
servers:
- dev.example.com
- another.example.com
1
2
my.servers[0]=dev.example.com
my.servers[1]=another.example.com

这两种方式都是定义了一个使用属性值,在代码中可以这样使用:

1
2
3
4
5
6
7
8
9
@ConfigurationProperties(prefix="my")
public class Config {

private List<String> servers = new ArrayList<String>();

public List<String> getServers() {
return this.servers;
}
}

yml的缺点

@PropertySource 无法加载yml文件,如果你需要使用这种方式去加载配置文件,必须使用properties

到这里正常使用SpringBoot的配置文件已经没有什么问题了,想解锁更高阶的用法请移步官方文档,或者等我后续更新