SpringBoot 源码深度解析
第三章 SpringBoot 全局配置文件前言
springBoot的全局配置文件
一、全局配置文件概述及优先级
全局配置文件能够对一些默认配置值进行修改及自定义配置。
Spring Boot
使用一个application.properties
或者application.yaml
的文件作为全局配置文件:
也可以从ConfigFileApplicationListener
这类便可看出,其DEFAULT_SEARCH_LOCATIONS
属性设置了加载的目录:
翻译成文件系统:
–file:./config/
–file:./
–classpath:/config/
–classpath:/
那么运行上述项目,访问端口会是什么呢?—8081
按照优先级从高到低的顺序 :
1.先去项目根目录找config文件夹下找配置文件件
2.再去根目录下找配置文件
3.去resources下找cofnig文件夹下找配置文件
4.去resources下找配置文件
整个设计非常巧妙。SpringBoot会从这四个位置全部加载主配置文件,如果高优先级中配置文件属性与低优先级配置文件不冲突的属性,则会共同存在— 互补配置 。
SpringBoot会加载全部主配置文件;互补配置;
这里说的配置文件,都还是项目里面。最终都会被打进jar包里面的,需要注意:
1、如果同一个目录下,有application.yml也有application.properties,默认先读取 application.properties。
2、如果同一个配置属性,在多个配置文件都配置了,默认使用第1个读取到的,后面读取的不覆盖前面读取到的。
3、创建SpringBoot项目时,一般的配置文件放置在项目的resources目录下
如果我们的配置文件名字不叫application.properties
或者application.yml
,可以通过以下参数来指定配置文件的名字,myproject
是配置文件名
$ java -jar myproject.jar --spring.config.name=myproject
我们同时也可以指定其他位置的配置文件来生效,指定配置文件和默认加载的这些配置文件共同起作用形成互补配置。
java -jar run-0.0.1-SNAPSHOT.jar -- spring.config.location=D:/application.properties
注意:
Spring Boot 2.4
改进了处理 application.properties
和 application.yml
配置文件的方式,
如果是2.4.0之前版本,优先级properties>yaml
但是如果是2.4.0的版本,优先级yaml>properties
如果想继续使用 Spring Boot 2.3
的配置逻辑,也可以通过在 application.properties
或者application.yml
配置文件中添加以下参数:
spring.config.use-legacy-processing = true
二、application.properties配置文件详解
使用Spring Initializr
方式构建Spring Boot
项目时,会在resource
目录下自动生成一个空的
application.properties
文件,Spring Boot
项目启动时会自动加载application.properties
文件。我们可以在application.properties
文件中定义Spring Boot
项目的相关属性,当然,这些相关属性可以是系统属性、环境变量、命令参数等信息,也可以是自定义配置文件名称和位置
server.port=8081
spring.datasource.driver-class-name=com.mysql.jdbc.Driver spring.config.name=application
对于server开头的系统属性,我们可以找到org.springframework.boot:spring-autoConfigure 下的 spring.factorys文件,找到这个文件中的org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration,点击进入,找到@EnableConfigurationProperties({ServerProperties.class})注解,点击进入ServerProperties.class。在ServerProperties类中,就是前缀为server的各种属性,这些属性均会使用application.properties配置的内容,并使用set注入的方式进行注入
那么如何使用自定义属性呢?
通过一个例子简单演示一下:
- 先创建一个pojo包,并在该包下创建两个实体类Pet和Person
public class Pet {
private String type;
private String name;
// 省略属性getXX()和setXX()方法
// 省略toString()方法
}
@Component
@ConfigurationProperties(prefix = "person")
public class Person {
private int id; //id
private String name; //名称
private List hobby; //爱好
private String[] family; //家庭成员
private Map map;
private Pet pet; //宠物
// 省略属性getXX()和setXX()方法
// 省略toString()方法
}
其中@ConfigurationProperties(prefix = "person")
注解的作用是将配置文件中以person
开头的属性值通过setXX()方法注入到实体类对应属性中
在编写实体类的时候你会发现
idea这样一个提示,这个提示就是说你在这里自定义的标签没有进行一个配置,具体体现在编写application.properties
时没有Person
标签的提示;所以需要引入一个依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
需要注意的是,在pom.xml
中添加上述配置依赖后,还需要重新运行项目启动类或者使用“Ctrl+F9”快捷重构当前Spring Boot
项目方可生效
- 打开项目的resources目录下的application.properties配置文件,在该配置文件中编写需要对Person类设置的配置属性
执行测试方法测试一下:
可以看出,测试方法运行成功,同时正确打印出了Person
实体类对象。至此,说明application.properties
配置文件属性配置正确,并通过相关注解自动完成了属性注入
三、application.yaml配置文件详解
YAML
文件格式是Spring Boot
支持的一种JSON
超集文件格式,以数据为中心,比properties
、xml
等更适合做配置文件
●
yml
和xml
相比,少了一些结构化的代码,使数据更直接,一目了然
● l 相比properties
文件更简洁
●YAML
文件的扩展名可以使用.yml
或者.yaml
。
●application.yml
文件使用“key:(空格)value”
格式配置属性,使用缩进控制层级关系。
这里,针对不同数据类型的属性值,介绍一下YAML
- value值为普通数据类型(例如数字、字符串、布尔等)
当YAML配置文件中配置的属性值为普通数据类型时,可以直接配置对应的属性值,同时对于字符串类型的属性值,不需要额外添加引号,示例代码如下:
server:
port: 8080
servlet:
context-path: /hello
- value值为数组和单列集合
当YAML配置文件中配置的属性值为数组或单列集合类型时,主要有两种书写方式:缩进式写法和行内式写法。
其中,缩进式写法还有两种表示形式,示例代码如下:
person:
hobby:
- play
- read
- sleep
或者
person:
hobby:
play,
read,
sleep
上述代码中,在YAML
配置文件中通过两种缩进式写法对person
对象的单列集合(或数组)类型的爱好hobby
赋值为play
、read
和sleep
。其中一种形式为“-(空格)属性值”,另一种形式为多个属性值之前加英文逗号分隔(注意,最后一个属性值后不要加逗号)。
person:
hobby: [play,read,sleep]
- value值为Map集合和对象
当YAML配置文件中配置的属性值为Map集合或对象类型时,YAML配置文件格式同样可以分为两种书写方式:缩进式写法和行内式写法。其中,缩进式写法的示例代码如下:
person:
map:
k1: v1
k2: v2
对应的行内式写法示例代码如下:
person:
map: {k1: v1,k2: v2}
在YAML
配置文件中,配置的属性值为Map
集合或对象类型时,缩进式写法的形式按照YAML
文件格式编写即可,而行内式写法的属性值要用大括号“{}”包含。
那么上面那个文件就可以这么写:
person:
id: 1
name: lucy
hobby: [吃饭,睡觉,打豆豆]
family: [father,mother]
map: {k1: v1,k2: v2}
pet: {type: dog,name: 旺财}