Spring Boot 资源配置文件读取

在实际开发中,我们会遇到关于配置文件的读取,获取配置文件的自定义配置,以及如何多环境下的配置文件信息的获取。

配置读取优先级

  1. 命令行参数。

  2. java:comp/env 得到的 JNDI 属性。

  3. 通过 System.getProperties() 获取的 Java 系统参数。

  4. 操作系统环境变量。

  5. RandomValuePropertySource 配置的 random.* 属性值。如 ${random.int}、${random.long}、${random.value}、${random.uuid} 等。

  6. JAR 包外部的 application-{profile}.propertiesapplication.yml (带 spring.profile)配置文件。

  7. JAR 包内部的 application-{profile}.propertiesapplication.yml (带 spring.profile)配置文件。

  8. JAR 包外部的 application.propertiesapplication.yml(不带 spring.profile)配置文件。

  9. JAR 包内部的 application.propertiesapplication.yml(不带 spring.profile)配置文件。
    (从 JAR 包外向 JAR 包内进行寻找,优先加载带 {profile} 的文件,再加载不带 {profile}的文件)

  10. @Configuration 注解类上的 @PropertySource

  11. 通过 SpringApplication.setDefaultProperties 指定默认属性。

注意:application.properties 文件的优先级高于 application.yml 文件的优先级。

配置依赖项

在 pom.xml 文件中,加入 spring-boot-configuration-processor 依赖项,用于读取配置值。

1
<dependency>
2
  <groupId>org.springframework.boot</groupId>
3
  <artifactId>spring-boot-configuration-processor</artifactId>
4
  <optional>true</optional>
5
</dependency>

属性配置与实体类的映射

  • application.properties
1
# 32 位随机字符串
2
rand.stringValue = ${random.value}
3
# 随机的 int 类型数字
4
rand.intNumber = ${random.int}
5
# 随机的 long 类型数字
6
rand.longNumber = ${random.long}
7
# 100 以内的随机int类型
8
rand.number = ${random.int(100)}
9
# 0-100 范围内的随机int类型
10
rand.rangeNumber = ${random.int[0,100]}
  • author.properties
1
author.name = yifanzheng
2
author.nickname = star
3
author.intro = good boy!

方式一

@Configuration 注解的类上加上 @ConfigurationProperties(prefix="前缀名") 注解,可以使用 @PropertySource 注解指定加载的配置文件,不加时默认加载 application.properties 文件

1
/**
2
 * AuthorConfig
3
 *
4
 * @author star
5
 **/
6
@Configuration
7
@ConfigurationProperties(prefix = "author")
8
@PropertySource(value = "classpath:author.properties") // 指定配置文件的位置
9
public class AuthorConfig {
10
11
    private String name;
12
13
    private String nickname;
14
15
    private String intro;
16
17
    public String getName() {
18
        return name;
19
    }
20
21
    public void setName(String name) {
22
        this.name = name;
23
    }
24
25
    public String getNickname() {
26
        return nickname;
27
    }
28
29
    public void setNickname(String nickname) {
30
        this.nickname = nickname;
31
    }
32
}

注意:使用这种方式配置的类,在使用 @Autowired 注入时,不能直接 return 注入的对象,它只是指向 Spring 容器中对象资源的一个标识,可以通过这个标识返回该对象中的值。

方式二

使用 @Value 注解,直接映射实体类的各个属性。

1
/*
2
 * RandomConfig
3
 *
4
 * @author star
5
 **/
6
@Component
7
public class RandomConfig {
8
9
    @Value("${rand.stringValue}")
10
    private String stringValue;
11
12
    @Value("${rand.intNumber}")
13
    private Integer intNumber;
14
15
    @Value("${rand.longNumber}")
16
    private Long longNumber;
17
18
    @Value("${rand.number}")
19
    private Integer number;
20
21
    @Value("${rand.rangeNumber}")
22
    private Integer rangeNumber;
23
24
    public String getStringValue() {
25
        return stringValue;
26
    }
27
28
    public void setStringValue(String stringValue) {
29
        this.stringValue = stringValue;
30
    }
31
32
    public Integer getIntNumber() {
33
        return intNumber;
34
    }
35
36
    public void setIntNumber(Integer intNumber) {
37
        this.intNumber = intNumber;
38
    }
39
40
    public Long getLongNumber() {
41
        return longNumber;
42
    }
43
44
    public void setLongNumber(Long longNumber) {
45
        this.longNumber = longNumber;
46
    }
47
48
    public Integer getNumber() {
49
        return number;
50
    }
51
52
    public void setNumber(Integer number) {
53
        this.number = number;
54
    }
55
56
    public Integer getRangeNumber() {
57
        return rangeNumber;
58
    }
59
60
    public void setRangeNumber(Integer rangeNumber) {
61
        this.rangeNumber = rangeNumber;
62
    }
63
}

方式三

在方法上使用 @Bean 注解,配合以上注解使用。

1
/**
2
 * AuthorBeanConfig 使用 @Bean 注解的方式获取配置信息
3
 *
4
 * @author star
5
 **/
6
@Configuration
7
@PropertySource(value = "classpath:author.properties")
8
public class AuthorBeanConfig {
9
10
    @Bean
11
    @ConfigurationProperties(prefix = "author")
12
    public AuthorBean getAuthorBean(){
13
       return new AuthorBean();
14
    }
15
}

在没有使用 @PropertySource 注解指定加载的文件时,默认使用 application.properties 文件中与实体对象的属性相同的配置项。
@PropertySources 注解优先级比较低,即使指定了加载的文件,但出现与 application.properties 文件相同的配置项时会被其覆盖。

自定义 YAML 资源文件属性配置

  • 创建 user.yml 文件,进行属性配置
1
# 配置 user 对象的值
2
demo:
3
 user:
4
  name: star
5
  age: 22
6
  desc: good boy!
  • 使用注解标记 User.java 对象文件
1
/**
2
 * UserConfig
3
 *
4
 * @author star
5
 **/
6
@Configuration
7
@ConfigurationProperties(prefix = "demo.user") // 前缀名注释必须有,不然会报错
8
@PropertySource(value = "classpath:user.yml",encoding = "utf-8")
9
public class User {
10
    // @Value() 注解必须要
11
    @Value("${name}")
12
    private String name;
13
14
    @Value("${age}")
15
    private int age;
16
17
    @Value("${desc}")
18
    private String desc;
19
20
    public String getName() {
21
        return name;
22
    }
23
24
    public void setName(String name) {
25
        this.name = name;
26
    }
27
28
    public int getAge() {
29
        return age;
30
    }
31
32
    public void setAge(int age) {
33
        this.age = age;
34
    }
35
36
    public String getDesc() {
37
        return desc;
38
    }
39
40
    public void setDesc(String desc) {
41
        this.desc = desc;
42
    }
43
}

多环境配置

application-dev.properties: 开发环境
application-prod.properties: 生产环境

Spring Boot 通过 application.roperties 文件,设置 spring.profiles.active 属性加载相应的文件,如:spring.profiles.active=dev

注意:Spring Boot 根据环境激活配置文件的规则是,默认加载 application.properties 文件,当此文件配置了 spring.profiles.active=xxx 后,会加载 application-xxx.properties 文件中的配置项,并覆盖 application.properties 中相同的配置项。

最后

  • 使用 YAML 文件时,属性值和冒号中间必须要有空格。
  • YAML 文件在配置中文值时,读取不会出现乱码问题;properties 文件配置中文值,读取会出现乱码。因为 Spring Boot 是以 iso-8859-1 的编码格式读取 properties 文件。

源码地址

springboot-properties