SpringBoot使用默认的全局的配置文件:application.properties
/application.yml
配置文件名固定是是application
`application.properties`语法结构: key=value`application.yml`语法结构: key:空格 value
SpringBoot在底层给我们自动做了一些配置,所以springboot项目不编写配置文件也可以正常运行,但是根据我们的具体开发我们需要修改SpringBoot自动配置的默认值;
比如我们可以更改默认启动的端口号
在application.properties
中添加
#更改项目端口号
server.port=8081
然后重新启动,可以看到启动的端口号变更
然后访问localhost:8081
即可
springboot启动会扫描以下位置的
application.properties
/application.yml
文件作为其默认配置文件:
优先级1:项目路径下的config文件夹配置文件
优先级2:项目路径下配置文件
优先级3:资源路径下的config文件夹配置文件
优先级4:资源路径下配置文件
可以发现:springboot项目生成时的默认配置文件优先级是最低的
优先级由高到底,高优先级的配置会覆盖低优先级的配置;
SpringBoot会从这四个位置全部加载主配置文件;互补配置;
我们在最低级的两个配置文件中设置项目访问路径和端口号的配置来测试互补问题
在默认位置(第四加载位置)的properties
和yaml
两个配置文件中添加以下代码测试
#配置项目的访问路径
server.servlet.context-path=/zsr
server:servlet:context-path: /zzz #配置项目的访问路径port: 8081 #配置端口号
然后启动项目测试,可以看到,最终配置的项目访问路径是/zsr
,且访问端口为8081
因此:当两个配置文件同时存在的时候,相同的配置会优先加载properties
配置文件,多余的配置的会互补配置;
实际开发中,我们针对不同的应用场景,可能有不同的环境,不同的配置文件
profile
就是Spring对不同环境提供不同配置功能的支持,可以通过激活不同的环境版本,实现快速切换环境,
我们再编写配置文件时,文件名可以是application-{profile}.properties/yml
,用来指定多个不同的环境版本;
例如(properties格式)
application.properties
代表主环境
# /src/main/resources/application.properties
server.port=8080
application-test.properties
代表测试环境配置
# /src/main/resources/application-test.properties
server.port=8081
application-dev.properties
代表开发环境配置
# /src/main/resources/application-dev.properties
server.port=8082
当我们运行测试时,如果未加指定,它默认使用application.properties
主配置文件;
实际开发中,面对不同的环境,我们可以在默认配置文件application,properties
中指定所需的配置文件环境,例如以下指定使用dev
的配置文件:
# /src/main/resources/application.properties
server.port=8080
spring.profiles.active=dev
此后再启动SpringBoot,就可以看到已经切换到dev下的配置环境;
YAML格式亦是如此
yaml多文档块:可以在一个配置文件中配置多个环境并根据需要进行选择,无需上述多个配置文件,更为方便
server: port: 8080
#选择要激活那个环境块
spring: profiles: active: prod---
server: port: 8081
spring: profiles: dev #配置环境名称dev---
server: port: 8082
spring: profiles: prod #配置环境名称prod
注意:如果yml和 properties的配置文件同时存在,同时都配置了端口,但是yaml多环境没有指定环境,默认会使用properties配置文件的!
当我们新建一个项目Springboot项目时,默认使用
properties
格式的配置文件,其实SpringBoot还支持yaml
格式的配置文件,且这是最流行,最为广泛使用的
YAML
有两种展开方式:
YAML Ain't a Markup Language
:YAML 不是一种标记语言
Yet Another Markup Language
:YAML是一种标记语言
之所以用反向缩略语重命名,是为了强调 YAML以数据做为中心,而不是以标记语言为重点
功能:
YAML的语法和其他高级语言类似,并且可以简单表达清单、散列表,标量等数据形态。
它使用空白符号缩进和大量依赖外观的特色,特别适合用来表达或编辑数据结构、各种配置文件、倾印调试内容、文件大纲(例如:许多电子邮件标题格式和YAML非常接近)
以前的配置文件,大多数都是使用 XML 来配置;
YAML
作为一种比 XML 更为简单易读的序列化语言,正越来越多地被用于应用及配置文件的开发中
比如一个简单的端口配置,我们来对比下yaml和xml:
<server><port>8081<port>
server>
#YAML配置
server&#xff1a;prot: 8080
简单的一个对比就可以看出&#xff1a;YAML可读性好&#xff0c;易于实现
不仅如此&#xff0c;YAML还有很多其他有点&#xff1a;
总之&#xff0c;YAML试图用一种比XML更敏捷的方式&#xff0c;来完成XML所完成的任务
#
表示注释YAML 支持以下几种数据类型&#xff1a;
对象
&#xff1a;键值对的集合&#xff0c;又称为映射&#xff08;mapping&#xff09;/ 哈希&#xff08;hashes&#xff09; / 字典&#xff08;dictionary&#xff09;数组
&#xff1a;一组按次序排列的值&#xff0c;又称为序列&#xff08;sequence&#xff09; / 列表&#xff08;list&#xff09;纯量
&#xff08;scalars&#xff09;&#xff1a;单个的、不可再分的值
对象键值对使用冒号结构表示 key: value
&#xff0c;冒号后面要加一个空格。
password: 123456
对象的行内写法&#xff1a;
User: {name: zsr,age: 20}
还可以使用缩进表示层级关系&#xff1a;
User:name: zsrage: 20
用 -
值表示数组中的一个元素,比如&#xff1a;
pets:- cat- dog- pig
行内写法
pets: [cat,dog,pig]
数据结构的子成员是一个数组&#xff0c;则可以在该项下面缩进一个空格&#xff0c;例如&#xff1a;
companies:-id: 1name: company1price: 200W-id: 2name: company2price: 500W
意思是 companies 属性是一个数组&#xff0c;每一个数组元素又是由 id、name、price 三个属性构成。
数组也可以使用流式(flow)的方式表示&#xff1a;
companies: [{id: 1,name: company1,price: 200W},{id: 2,name: company2,price: 500W}]
纯量
是最基本的&#xff0c;不可再分的值&#xff0c;包括&#xff1a;
- 字符串
- 布尔值
- 整数
- 浮点数
- Null
- 时间
- 日期
纯量直接写在后面就可以&#xff0c;字符串默认不用加上双引号或者单引号&#xff1b;
key: value
当写一些特殊字符时&#xff0c;我们可能会用上单引号或者双引号&#xff1a;
" "
双引号&#xff1a;不会转义字符串里面的特殊字符 &#xff0c; 特殊字符会作为本身想表示的意思&#xff1b;
#比如
name: "kuang \n shen"
#输出
kuang 换行 shen
&#39; &#39;
单引号&#xff1a;会转义特殊字符 &#xff0c; 特殊字符最终会变成和普通字符一样输出
#比如
name: ‘kuang \n shen’
#输出
kuang \n shen
使用一个例子来快速了解纯量的基本使用&#xff1a;
boolean: - TRUE #true,True都可以- FALSE #false&#xff0c;False都可以
float:- 3.14- 6.8523015e&#43;5 #可以使用科学计数法
int:- 123- 0b1010_0111_0100_1010_1110 #二进制表示
null:nodeName: &#39;node&#39;parent: ~ #使用~表示null
string:- 哈哈- &#39;Hello world&#39; #可以使用双引号或者单引号包裹特殊字符- newlinenewline2 #字符串可以拆成多行,每一行会被转化成一个空格
date:- 2018-02-17 #日期必须使用ISO 8601格式,即yyyy-MM-dd
datetime: - 2018-02-17T15:02:31&#43;08:00 #时间使用ISO 8601格式,时和日期之间使用T连接,最后使用&#43;代表时区
yaml文件更强大的地方在于&#xff0c;他可以给我们的实体类直接注入匹配值&#xff01;
在主程序同级目录下新建
pojo包
&#xff0c;在包下新建一个Dog
实体类
package com.zsr.pojo;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.stereotype.Component;&#64;Data
&#64;AllArgsConstructor//有参构造
&#64;NoArgsConstructor//无参构造
&#64;Component//注册bean到容器中
public class Dog {private String name;private Integer age;
}
Person类&#xff0c;包含所有常见数据类型&#xff0c;以及
Dog
对象
&#64;Data
&#64;AllArgsConstructor
&#64;NoArgsConstructor
&#64;Component //注册bean到容器中
public class Person {private String name;private Integer age;private Boolean happy;private Date birth;private Map<String, Object> maps;private List<Object> lists;private Dog dog;
}
在springboot项目中的resources目录下新建一个文件
application.yml
&#xff0c;使用yaml配置的方式进行注入
person:name: zsrage: 20happy: Truebirth: 2000/02/04maps: {k1: v1,k2: v2}lists:- guitar- sing- playdog:name: 多多age: 4
刚才已经把person对象的所有属性值都写好了
再通过
&#64;ConfigurationProperties
注解注入到我们的类中&#xff0c;
/*
&#64;ConfigurationProperties作用&#xff1a;将配置文件中配置的每一个属性的值&#xff0c;映射到这个组件中&#xff1b;告诉SpringBoot将本类中的所有属性和配置文件中相关的配置进行绑定参数 prefix &#61; “person” : 将配置文件中的person下面的所有属性一一对应
*/
&#64;Component //注册bean
&#64;ConfigurationProperties(prefix &#61; "person")
public class Person {private String name;private Integer age;private Boolean happy;private Date birth;private Map<String,Object> maps;private List<Object> lists;private Dog dog;
}
IDEA爆红提示&#xff1a;springboot配置注解处理器没有找到&#xff0c;我们点击Open Document
查看文档
发现未找到&#xff0c;我们降低版本为2.1.9
即可
https://docs.spring.io/spring-boot/docs/2.1.9.RELEASE/reference/html/configuration-metadata.html#configuration-metadata-annotation-processor
进入到网页中&#xff0c;可以找到一个依赖&#xff0c;加上他&#xff0c;就不会爆红提示
<dependency><groupId>org.springframework.bootgroupId><artifactId>spring-boot-configuration-processorartifactId><optional>trueoptional>
dependency>
配置完成后&#xff0c;我们修改测试类进行测试
package com.zsr;import com.zsr.pojo.Dog;
import com.zsr.pojo.Person;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;&#64;SpringBootTest
class Springboot02ConfigApplicationTests {&#64;Autowired //将person自动注入进来private Person person;&#64;Testvoid contextLoads() {System.out.println(person); //打印看下person对象}
}
结果&#xff1a;所有值全部注入成功&#xff01;yaml配置成功注入到实体类&#xff01;
以上我们通过
&#64;configurationProperties
注解默认从全局配置文件中获取值
此时配置文件名必须为
application
才能被spring认出其实我们可以通过
&#64;PropertySource
指定加载的配置文件&#xff0c;可以自定义文件名
1、我们去在resources目录下新建一个person.properties
文件
name&#61;zsr
age&#61;20
happy&#61;True
birth&#61;2000/02/04
lists&#61;guitar,sing,play
2、相应修改对应的实体类&#xff0c;用&#64;PropertySource
注解加载指定person.properties
文件
package com.zsr.pojo;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;import java.util.Date;
import java.util.List;
import java.util.Map;&#64;Data
&#64;AllArgsConstructor
&#64;NoArgsConstructor
&#64;Component //注册bean到容器中
&#64;PropertySource(value &#61; "classpath:person.properties")
public class Person {//SPEL表达式取出指定的值&#64;Value("${name}")private String name;&#64;Value("${age}")private Integer age;&#64;Value("${happy}")private Boolean happy;&#64;Value("${birth}")private Date birth;private Map<String, Object> maps;&#64;Value("${lists}")private List<Object> lists;//properties不能存对象private Dog dog;
}
3、修改测试类
package com.zsr;import com.zsr.pojo.Dog;
import com.zsr.pojo.Person;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;&#64;SpringBootTest
class Springboot02ConfigApplicationTests {&#64;Autowired //将person自动注入进来private Person person;&#64;Testvoid contextLoads() {System.out.println(person); //打印看下person对象}
}
4、运行测试
指定配置文件绑定成功&#xff01;
yaml配置文件还可以编写占位符生成随机数
person:name: zsr${random.uuid} # 随机uuidage: ${random.int} # 随机inthappy: truebirth: 2000/02/04maps: {k1: v1,k2: v2}lists:- guitar- sing- playdog:name: ${person.hello:other}_多多age: 4
然后运行测试&#xff1a;
以上采用的
yaml
配置文件是最简单且最常用的方式&#xff1b;也是springboot所推荐的&#xff01;接下来来对比一下默认的
properties
配置文件
注&#xff1a;properties配置文件在写中文的时候&#xff0c;会有乱码&#xff0c;我们需要去IDEA中设置编码格式为UTF-8&#xff1b;
1、新建一个实体类User
package com.zsr.pojo;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.stereotype.Component;&#64;Component
&#64;Data
&#64;AllArgsConstructor
&#64;NoArgsConstructor
public class User {private String name;private int age;private String sex;
}
2、编辑配置文件 user.properties
name&#61;zsr
3、我们在User类上使用&#64;Value来进行注入&#xff01;
package com.zsr.pojo;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;
import org.springframework.beans.factory.annotation.Value;&#64;Component
&#64;Data
&#64;AllArgsConstructor
&#64;NoArgsConstructor
&#64;PropertySource(value &#61; "classpath:user.properties")
public class User {//直接使用&#64;value()&#64;Value("${user.name}")//从配置文件中取值private String name;&#64;Value("#{9*2}")//SPEL表达式:&#64;Value("#{表达式}")private int age;&#64;Value("男") //纯量private String sex;
}
4、Springboot测试类测试
package com.zsr;import com.zsr.pojo.Person;
import com.zsr.pojo.User;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;&#64;SpringBootTest
class Springboot02ConfigApplicationTests {&#64;Autowired //将user自动注入进来private User user;&#64;Testvoid contextLoads() {System.out.println(user); //打印看下person对象}}
结果正常输出&#xff1a;
&#64;ConfigurationProperties
只需要写一次即可&#xff0c;&#64;Value
则需要对每个字段都添加
松散绑定
&#xff1a;比如我的yaml中写的 last-name&#xff0c;这个和 lastName 是一样的&#xff0c;-
后面跟着的字母默认是大写的&#xff0c;这就是松散绑定
JSR303数据校验
&#xff1a;可以在字段是增加一层过滤器验证&#xff0c;可以保证数据的合法性
复杂类型封装
&#xff1a;yaml中可以封装对象&#xff0c;使用&#64;value就不支持
最佳实践&#xff1a;
配置 yaml 和配置 properties 都可以获取到值时&#xff0c;首荐 yaml&#xff1b;
如果在某个业务中&#xff0c;只需要获取配置文件中的某个值&#xff0c;可以使用一下&#64;value
如果有编写的JavaBean来和配置文件进行一一映射&#xff0c;就直接&#64;configurationProperties