参考文献

YAML格式

  • 以空格的缩进程度来控制层级关系。空格的个数并不重要,只要左边空格对齐
    则视为同一个层级。注意不能用 tab 代替空格。且大小写敏感。支持字面值,
    对象,数组三种数据结构,也支持复合结构。
  • 字面值:字符串,布尔类型,数值,日期。字符串默认不加引号,单引号会转
    义特殊字符。日期格式支持 yyyy/MM/dd HH:mm:ss
  • 对象:由键值对组成,形如 key:(空格)value 的数据组成。冒号后面的空格是
    必须要有的,每组键值对占用一行,且缩进的程度要一致,也可以使用行内写
    法: {k1: v1, ....kn: vn}
  • 数组:由形如 -(空格)value 的数据组成。短横线后面的空格是必须要有的,每
    组数据占用一行,且缩进的程度要一致,也可以使用行内写法: [1,2,...n]
  • 复合结构:上面三种数据结构任意组合

示例

1
2
3
4
5
6
7
8
9
10
userinfo:
  age: 25
  name: myjszl
  active: true
  created-date: 2018/03/31 16:54:30
  map: {k1: v1,k2: v2}
  hobbies:
    - one
    - two
    - three
  • 配置对应的实体类
1
2
3
4
5
6
7
8
9
10
@Data
@ToString
public class UserInfo {
   private String name;
   private Integer age;
   private Boolean active;
   private Map<String,Object> map;
   private Date createdDate;
   private List<String> hobbies;
}

SpringBoot读取Yaml配置

@ConfigurationProperties

  • 用于从配置文件中取值,这次会复杂的数据类型,但不支持SPEL表达式.
  • 该注解中有一个属性prefix,用于指定获取配置的前缀.
  • 该注解可以标注在类上也可以标注在方法上,即有两种获取值的方式.
标注在实体类上
  • 这种方式用于从实体类上取值,并且赋值到对应的属性。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/**
* @Component :注入到IOC容器中
* @ConfigurationProperties:从配置文件中读取文件
*/
@Component
@ConfigurationProperties(prefix = "userinfo")
@Data
@ToString
public class UserInfo {
   private String name;
   private Integer age;
   private Boolean active;
   private Map<String,Object> map;
   private Date createdDate;
   private List<String> hobbies;
}
标注在配置类的方法上
  • 标注在配置类上的方法上,同样是从配置文件中取值赋值到返回值的属性中。
1
2
3
4
5
6
7
8
9
10
   /**
    * @Bean : 将返回的结果注入到IOC容器中
    * @ConfigurationProperties :从配置文件中取值
    * @return
    */
   @ConfigurationProperties(prefix = "userinfo")
   @Bean
   public UserInfo userInfo(){
       return new UserInfo();
 }
优点
  • @ConfigurationProperties注解能够很轻松的从配置文件中取值,优点如下:
    1. 支持批量的注入属性,只需要指定一个前缀 prefix
    2. 支持复杂的数据类型,比如 List ,Map.
    3. 对属性名匹配的要求较低,比如user-name,user_name,userNameUSER_NAME 都可以取值.
    4. 支持JavaJSR303数据校验
  • 注意:@ConfigurationProperties 这个注解仅仅是支持从Spring Boot的默认配置文件中取值,比如 application.properties,application.yml

@Value

  • Spring中从属性取值的注解,支持SPEL表达式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
package com.holelin.sundry.test.yaml;

import com.holelin.sundry.SundryApplication;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import java.util.List;
import java.util.Map;

/**
* @Description:
* @Author: HoleLin
* @CreateDate: 2022/8/2 10:45
* @UpdateUser: HoleLin
* @UpdateDate: 2022/8/2 10:45
* @UpdateRemark: 修改内容
* @Version: 1.0
*/
@Slf4j
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
classes = SundryApplication.class)
public class ValueTest {

@Value("${test.list.ids:1,2,3}")
private List<String> list;

@Value("${test.list.ids:1,2,3}")
private String[] stringArray;

@Value("#{'${test.list.topics}'.split(',')}")
private List<String> topics;

@Value("#{${test.maps}}")
private Map<String, String> maps;

@Test
public void testValueWithList() {
log.info("list:{}", list);
}

@Test
public void testValueWithArray() {
log.info("stringArray:{}", stringArray.length);
}

@Test
public void testValueWithSPEL() {
log.info("topics:{}", topics);
}

@Test
public void testValueWithMap() {
log.info("maps:{}", maps);
}
}
// output
2022-08-02 11:18:58.892 [main] INFO com.holelin.sundry.test.yaml.ValueTest - stringArray:3
2022-08-02 11:18:58.901 [main] INFO com.holelin.sundry.test.yaml.ValueTest - maps:{key1=value1, key2=value2}
2022-08-02 11:18:58.906 [main] INFO com.holelin.sundry.test.yaml.ValueTest - list:[1, 2, 3]
2022-08-02 11:18:58.911 [main] INFO com.holelin.sundry.test.yaml.ValueTest - topics:[topic1, topic2, topic3]

@ConfigurationProperties@Value的区别

二者区别 @ConfigurationProperties @Value
功能 批量注入配置文件中的属性 一个个指定
松散绑定(松散语法) 支持 不支持
SpEL 不支持 支持
JSR303数据校验 支持 不支持
复杂类型封装 支持 不支持

从自定义配置文件中取值

  • Spring Boot在启动的时候会自动加载 application.xxxbootsrap.xxx,从自定义配置文件取值则需要使用@PropertySource注解

    1
    2
    3
    @SpringBootApplication
    @PropertySource(value = {"classpath:custom.properties"})
    public class SundryApplication {}
  • @PropertySource注解value 属性是一个数组,可以指定多个配置文件同时引入。@PropertySource 默认加载xxx.properties类型的配置文件,不能加载YML格式的配置文件.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
package com.holelin.sundry.test.yaml;

import org.springframework.beans.factory.config.YamlPropertiesFactoryBean;
import org.springframework.core.env.PropertiesPropertySource;
import org.springframework.core.env.PropertySource;
import org.springframework.core.io.support.DefaultPropertySourceFactory;
import org.springframework.core.io.support.EncodedResource;

import java.io.IOException;
import java.util.Properties;
/**
* @Description:
* @Author: HoleLin
* @CreateDate: 2022/8/2 11:29
* @UpdateUser: HoleLin
* @UpdateDate: 2022/8/2 11:29
* @UpdateRemark: 修改内容
* @Version: 1.0
*/
public class YmlConfigFactory extends DefaultPropertySourceFactory {
@Override
public PropertySource<?> createPropertySource(String name,
EncodedResource resource) throws IOException {
String sourceName = name != null ? name :
resource.getResource().getFilename();
if (!resource.getResource().exists()) {
return new PropertiesPropertySource(sourceName, new Properties());
} else {
final String suffix = ".yml";
final String suffix1 = ".yaml";
if (sourceName.endsWith(suffix) ||
sourceName.endsWith(suffix1)) {
Properties propertiesFromYaml = loadYml(resource);
return new PropertiesPropertySource(sourceName,
propertiesFromYaml);
} else {
return super.createPropertySource(name, resource);
}
}
}

private Properties loadYml(EncodedResource resource) throws
IOException {
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
factory.setResources(resource.getResource());
factory.afterPropertiesSet();
return factory.getObject();
}
}
1
2
3
@SpringBootApplication
@PropertySource(value = {"classpath:custom.yml"}, factory = YmlConfigFactory.class)
public class SundryApplication {}

SpringBoot jar包指定外部启动配置文件

1
java -jar myproject.jar --spring.config.location=classpath:/default.properties,classpath:/override.properties
1
java -jar -Dspring.config.location=D:\config\config.properties springbootrestdemo-0.0.1-SNAPSHOT.jar 

Spring Boot uses a very particular PropertySource order that is designed to allow sensible overriding of values. Later property sources can override the values defined in earlier ones. Sources are considered in the following order:

  1. Default properties (specified by setting SpringApplication.setDefaultProperties).
  2. @PropertySource annotations on your @Configuration classes. Please note that such property sources are not added to the Environment until the application context is being refreshed. This is too late to configure certain properties such as logging.* and spring.main.* which are read before refresh begins.
  3. Config data (such as application.properties files).
  4. A RandomValuePropertySource that has properties only in random.*.
  5. OS environment variables.
  6. Java System properties (System.getProperties()).
  7. JNDI attributes from java:comp/env.
  8. ServletContext init parameters.
  9. ServletConfig init parameters.
  10. Properties from SPRING_APPLICATION_JSON (inline JSON embedded in an environment variable or system property).
  11. Command line arguments.
  12. properties attribute on your tests. Available on @SpringBootTest and the test annotations for testing a particular slice of your application.
  13. @DynamicPropertySource annotations in your tests.
  14. @TestPropertySource annotations on your tests.
  15. Devtools global settings properties in the $HOME/.config/spring-boot directory when devtools is active.

Config data files are considered in the following order:

  1. Application properties packaged inside your jar (application.properties and YAML variants).
  2. Profile-specific application properties packaged inside your jar (application-{profile}.properties and YAML variants).
  3. Application properties outside of your packaged jar (application.properties and YAML variants).
  4. Profile-specific application properties outside of your packaged jar (application-{profile}.properties and YAML variants).

It is recommended to stick with one format for your entire application. If you have configuration files with both .properties and YAML format in the same location, .properties takes precedence.