0%

spring boot | 配置文件

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


参考资料



文件格式


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

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

项目内可以同时存在 application.propertiesapplication.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

注意事项:我们只需要指定配置文件的名称即可,可以使用 propertiesyaml 文件格式,上面的配置会加载 src/main/resources/custome.ymlsrc/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. 指定路径之后,原来默认的文件还会加载吗?

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

  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.propertiesdevtools 处于活动状态时)。
  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. 打包的 jarapplication-{profile}.propertiesYAML 变体)之外的特定于配置文件的应用程序属性。
  13. 打包在 jar 中的特定于配置文件的应用程序属性(application-{profile}.propertiesYAML 变体)。
  14. 打包 jar 之外的应用程序属性(application.propertiesYAML 变体)。
  15. 打包在 jar 中的应用程序属性(application.propertiesYAML 变体)。
  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;
}

配置读取


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

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

请我喝杯咖啡吧~