0%

spring boot | 配置文件

这里将介绍 spting boot 的配置文件、多配置、自定义配置等。


参考资料



文件格式


在 Spring Boot 中,配置文件有两种不同的格式,一个是 properties ,另一个是 yaml 。

虽然 properties 文件比较常见,但是相对于 properties 而言,yaml 更加简洁明了,而且使用的场景也更多,很多开源项目都是使用 yaml 进行配置(例如 Hexo)。除了简洁,yaml 还有另外一个特点,就是 yaml 中的数据是有序的,properties 中的数据是无序的,在一些需要路径匹配的配置中,顺序就显得尤为重要(例如我们在 Spring Cloud Zuul 中的配置),此时我们一般采用 yaml。

项目内可以同时存在 application.properties、 application.yml 两个文件,经过测试发现, properties 优先级会高一些,相同名称的配置,会将 yml 内的配置覆盖掉。


文件顺序


spring boot 默认配置文件名为 application,其默认可放置顺序为 4 个地方。

  • 当前项目根目录下的 config 目录下
  • 当前项目的根目录下
  • resources 目录下的 config 目录下
  • resources 目录下

按如上顺序,四个配置文件的优先级依次降低。如下:

所谓的优先级,就是优先级最高的会覆盖优先级低的,如上面,相同配置,以 当前项目根目录下的 config 目录下,即优先级为 1 的文件内容为主。

我们可以从 ConfigFileApplicationListener 这类便可看出,其中DEFAULT_SEARCH_LOCATIONS属性设置了加载的目录:

private static final String DEFAULT_SEARCH_LOCATIONS = "classpath:/,classpath:/config/,file:./,file:./config/";

自定义文件名


有的时候,我们并不想使用 application 作为配置文件名,或者,我们想把配置文件放到其他地方。

两个方法

  • 指定名字
  • 指定路径

指定配置文件

如果你的应用程序配置文件的名称不是 application,你想要进行自定义,可以通过 --spring.config.name 命令行参数进行指定,如下所示:

java -jar project-sample.jar --spring.config.name=custome

注意事项:我们只需要指定配置文件的名称即可,可以使用 properties 或 yaml 文件格式,上面的配置会加载 src/main/resources/custome.yml 或 src/main/resources/custome.properties。

通过 --spring.config.name 仅仅是修改了配置文件的名称,那如果是修改配置文件所处的目录位置,我们需要怎么做呢?

修改配置文件目录

SpringBoot已经给我们准备好了,通过 --spring.config.location 参数就可以指定配置文件的位置,如下所示:

java -jar project-sample.jar --spring.config.location=classpath:/configs/custome.yml

如果一个配置文件无法满足你的需求,那你看看下面这个方式:

java -jar project-sample.jar --spring.config.location=classpath:/configs/custome.yml,classpath:/configs/default.properties

注意事项:支持通过命令行参数的方式指定多个配置文件,使用英文半角 , 隔开即可。

如果你通过 spring.config.location 指定的不是一个文件而是一个目录,在路径最后务必添加一个 / 结束,然后结合 spring.config.name 进行组合配置文件,组合示例如下:

加载/configs/application.properties 或/configs/application.yml(默认文件名)

java -jar project-sample.jar --spring.config.location=classpath:/configs/

加载/configs/custome.properties 或 /configs/custome.ymljava -jar project-sample.jar

--spring.config.location=classpath:/configs/ --spring.config.name=custome

注意事项: spring.config.name 该配置参数默认值为 application ,所以如果只是指定了 spring.config.location 并为目录形式,上面示例中会自动将 spring.config.name 追加到目录路径后,如果指定的 spring.config.location 并非是一个目录,这里会忽略 spring.config.name 的值。

ps: 这里还有两个问题需要回答。

  1. 指定路径之后,原来默认的文件还会加载吗?

指定文件之后,原来的默认文件不加载了。包括 yml 和 properties 文件,至于,指定路径后,依然想加载其他的配置文件,可以参考

  1. 如果指定多个加载文件,那么,优先级是怎么样的?

路径中,后面的配置文件优先级高。后面的会覆盖前面的。

还有在 IDEA 中,想要用不同的配置文件,图如下:


配置文件书写规则


这里只是我的经验,并没有进行系统考究。

这里主要有以下要素

  • 大小写
  • 顺序
  • 系统变量

大小写问题

在 application.yml 写下如下内容

1
2
3
logname:
Name: sss
NaMe: zzz

如果,我们要获取 logname.name 属性,获取的是 sss。

如果,内容改为

1
2
3
4
logname:
Name: sss
name: yyy
NaMe: zzz

那么,将会以全小写的 name 为主。

我在其他地方看到的

ps: SpringBoot下此种写法不区分大小写,驼峰,-,_等书写形式都是兼容的。但是你的字母必须对应上啊,比如上面的user你不能写成username了。比如我这样写:datasource.u-r-l=xxx也是能够被正常识别的~ 具体参照SpringBoot的黑科技类:RelaxedNames

系统变量

1
2
logname:
Name: ${}

文件读取顺序进阶


上面我们介绍了,4 个默认的配置文件,以及,自己可以自定义配置文件。但是,实际上,spring boot 默认加载的远不止那 4 个「可以发现那 4 个默认文件处于加载顺序的序号 17」,有如下加载顺序:

数字越小优先级越高。

  1. 主目录中的Devtools 全局设置属性(~/.spring-boot-devtools.properties当 devtools 处于活动状态时)。
  2. @TestPropertySource 测试中的注释。
  3. @SpringBootTest#properties 测试中的注释属性。
  4. 命令行参数。
  5. 来自SPRING_APPLICATION_JSON(嵌入在环境变量或系统属性中的内联 JSON)的属性。
  6. ServletConfig 初始化参数。
  7. ServletContext 初始化参数。
  8. JNDI 属性来自 java:comp/env.
  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和 YAML 变体)。
  16. @PropertySource 你的@Configuration类的注释。
  17. 默认属性(由 setting 指定SpringApplication.setDefaultProperties)。

我们来举一个简单的例子,用来验证上面加载顺序的实现。

首先,在任一 application.yml 中添加如下内容。

1
2
user:
name: ccc

然后,创建一个 User 类。

1
2
3
4
5
6
7
8
9
10
11
12
package com.jiezi.demo.entity;

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

@Data
@Component
@ConfigurationProperties(prefix = "user", ignoreUnknownFields = false)
public class User {
private String name;
}

然后在随意弄一个 controller

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package com.jiezi.demo.test;

import com.jiezi.demo.entity.User;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;

@RestController
public class HelloController {
@Resource
private User user;

@GetMapping("/test")
public String sayTest() {
return user.getName();
}

}

当运行之后,返回的 Name 是你系统的名称,而不是 ccc 。

问题出在

@ConfigurationProperties(prefix = "user", ignoreUnknownFields = false)

这句话中。 当 prefix = "user" 的时候,由于系统文件优先级更高,这个时候就会被替换成环境变量。

在 macbook 中,你可以用 env 来查看你的环境变量。

想要解决也很简单。

只需要将 application.yml 中换成如下内容。

1
2
person:
name: ccc

然后,User 类换成

1
2
3
4
5
6
7
8
9
10
11
12
package com.jiezi.demo.entity;

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

@Data
@Component
@ConfigurationProperties(prefix = "person", ignoreUnknownFields = false)
public class User {
private String name;
}

配置读取


了解完配置文件之后,那我们的重点就放在了如何读取配置文件中的值了。

在这里,请参考如下文章。

请我喝杯咖啡吧~