SpringBoot 配置文件详解(告别XML)
前言
上篇笔记中提到SpringBoot简化Spring的开发是通过大量的默认配置,然而在开发中我们有时需要改变这些默认约定,所以要使用配置文件。
配置文件
SpringBoot中的配置文件明必须是application,如:application.yml,application.properties,application.yaml
配置文件的作用: 帮我们修改自动配置的默认值;
YAML
YAML 语言(发音 /ˈjæməl/ )的设计目标,就是方便人类读写。它实质上是一种通用的数据串行化格式。
它的基本语法如下:
- 大小写敏感
- 使用缩进表示层级关系
- 缩进时不允许使用Tab键,只允许使用空格。
- 缩进的空格数目不重要,只要相同层级的元素左侧对齐即可
- # 表示注释, 作用一直到行尾
YAML支持的数据结构:
- 对象:键值对的集合,又称为映射(mapping)/ 哈希(hashes) / 字典(dictionary)
- 数组:一组按次序排列的值,又称为序列(sequence) / 列表(list)
- 纯量(scalars):单个的、不可再分的值
数据结构
纯量(字面量)
所谓的字面量就是指字符串,数字,布尔值等基本数据;
字符串默认不需要单引号和双引号,如果你非要用的话,请看下面的规则:
“”:双引号,不会转义字符串里面的特殊字符;特殊字符会作为本身想表示的意思
举个栗子:name: “zhangsan \n lisi”:输出;zhangsan 换行 lisi
‘’:单引号,会转义特殊字符,特殊字符最终只是一个普通的字符串数据
举个栗子:name: ‘zhangsan \n lisi’:输出;zhangsan \n lisi
对象(键值对的集合)
k: v:对象的一组键值对,使用冒号结构表示,冒号后必须有空格
pet: name: cat age: 2 sex: 公的
如果你愿意的话,也可以把它写成一行:
pet: { name: cat,gender: 公的,age: 22}
数组,List集合
基本写法
list: - item1 - item2 - item3
写成一行的话就是:
list: [item1,item2,item3]
开发实例
导入坐标
在pom.xml中加入如下坐标:
<!--导入配置文件处理器,配置文件进行绑定就会有提示--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> <optional>true</optional> </dependency>
编写实体类:
@Component @ConfigurationProperties(prefix = "person") public class Person { private String userName; private Integer age; private Date birthday; private Boolean sex; private Map<String,Object> map; private List<Object> list; private Cat cat; getter,setter,toString方法此处省略...... }
@Component public class Cat { private String name; private Integer age; getter,setter,toString方法此处省略...... }
配置文件
person: username: 张三 age: 18 birthday: 2020/02/26 sex: false map: { k1: v1,k2: 22} list: - item1 - item2 - item3 cat: name: 猫咪 age: 2
测试
@SpringBootTest class Day02SettingsApplicationTests { @Autowired Person person; @Test void contextLoads() { System.out.println(person); } }
properties
上述yaml配置等效:
person.user-name=张三 person.age=18 person.birthday=2020/02/26 person.sex=true person.map.k1=v1 person.map.k2=v2 person.list=item1,item2,item3 person.cat.name=猫咪 person.cat.age=2
当工程中同时有两种配置文件时,将以properties优先
中文乱码问题
如果使用properties配置时中文数据出现乱码,在设置中找到File Encoding,将配置文件字符设置为UTF-8,并且勾选Transparent native-to-ascii conversion
配置文件两种注入方式的对比
配置文件值注入有两种方式,一个是Spring Boot的@ConfigurationProperties注解,另一个是spring原先的@value注解
@Value | @ConfigurationProperties | |
---|---|---|
功能 | 一个个指定注入 | 批量注入配置文件中的属性 |
松散绑定 | 不支持 | 支持 |
SpEL | 支持 | 不支持 |
JSR303数据校验 | 不支持 | 支持 |
复杂类型封装 | 不支持 | 支持 |
松散绑定
例如Person中有lastName属性,在配置文件中可以写成lastName或lastname或last-name或last_name等等
SpEL
举个栗子:
配置文件
person.name=#{2019-1998+1}Person类
/** * 使用@ConfigurationProperties注解,会抛出异常 */ @Component @ConfigurationProperties(prefix = "person") public class Person { private Integer age; ---------------------------------------------------------------------------- /** * 使用@Value注解,正常注入 */ @Component public class Person { @Value("${person.age}") private Integer age;
JSR303数据校验
@ConfigurationProperties注解可以使用JSR303数据校验
@Value注解不支持数据校验
配置的其他知识
@PropertySource
@PropertySource注解的作用是加载指定位置的配置文件,其指可以是数组,即可以加载多个配置文件
SpringBoot默认加载的配置文件名称是application,如果配置文件名不是这个是不会被容器加载的。
使用这个注解加载配置文件就需要配置类使用@component等注解而不是等待@EnableConfigurationProperties激活,而且不支持yaml,只能是properties
@ImportResource
@ImportResource注解用于导入Spring的配置文件,让配置文件里面的内容生效;(就是以前写的springmvc.xml、applicationContext.xml)
Spring Boot里面没有Spring的配置文件,我们自己编写的配置文件,也不能自动识别;
想让Spring的配置文件生效,加载进来;必须把@ImportResource标注在一个配置类上
注意:此处应该把该注解加在入口类上而不是测试类
@Configuration
这是SpringBoot推荐的添加注解的方式,并且推荐使用全注解的方式。
配置类加上@Configuration相当于 Spring配置文件。
@Bean
使用@Bean给容器中添加组件,其中组件名就是方法名。
配置文件占位符
随机值
${ random.value} ${ random.int} ${ random.long} ${ random.int(10)} ${ random.int[1024,65536]}
引用配置好的其他属性
如果引用的属性没有值,可以使用:指定他的默认值
Profile
Profile是Spring对不同环境提供不同配置功能的支持,可以通过激活、指定参数等方式快速切换环境
多profile文件形式
此时运行程序,启动的是8080端口,但是我们可以自定义激活配置文件:
举个栗子:如果在主配置文件中加入以下代码
spring.profiles.active=dev再次运行程序,启动的则是我们配置的8081端口
yml支持多文档块
我们可以不用那么多的配置文件,只需要将主配置文件分块即可:
server: port: 8080 spring: profiles: active: prod --- server: port: 8081 spring: profiles: dev --- server: port: 8082 spring: profiles: prod
激活指定profile总结
-
在配置文件中指定 spring.profiles.active=dev(如上)
-
项目打包后在命令行启动
java -jar xxx.jar --spring.profiles.active=dev;
-
虚拟机参数
配置文件加载位置
springboot 启动会扫描以下位置的application.properties或者application.yml文件作为Spring boot的默认配置文件
file: ./config/ file: ./ classpath: /config/ classpath: /
优先级由高到底,高优先级的配置会覆盖低优先级的配置(优先级低的先加载);
SpringBoot会从这四个位置全部加载主配置文件;互补配置;
项目根目录下的配置文件maven在打包时不会编译进去,需要更改一下配置
<resources> <resource> <directory>.</directory> <filtering>true</filtering> <includes> <include>**/*.properties</include> <include>**/*.yaml</include> </includes> </resource> </resources>
还可以使用spring.config.location参数指定默认配置文件的位置
项目打包好以后,我们可以使用命令行参数的形式,启动项目的时候来指定配置文件的新位置;指定配置文件和默认加载的这些配置文件共同起作用形成互补配置;
java -jar xxx.jar --spring.config.location=/home/cheerway/application.yaml
外部配置加载顺序
SpringBoot也可以从以下位置加载配置; 优先级从高到低;高优先级的配置覆盖低优先级的配置,所有的配置会形成互补配置
-
命令行参数
所有的配置都可以在命令行上进行指定
java -jar xxx.jar --server.port=8087 --server.context-path=/abcCopy to clipboardErrorCopied
多个配置用空格分开; --配置项=值
-
来自java:comp/env的JNDI属性 ⤴️
-
Java系统属性(System.getProperties()) ⤴️
-
操作系统环境变量 ⤴️
-
RandomValuePropertySource配置的random.*属性值 ⤴️
由jar包外向jar包内进行寻找;
再来加载不带profile
- jar包外部的application.properties或application.yml(不带spring.profile)配置文件 ⤴️
- **jar包内部的application.properties或application.yml(不带spring.profile)配置文件 **⤴️
优先加载带profile
-
jar包外部的application-{profile}.properties或application.yml(带spring.profile)配置文件 ⤴️
-
**jar包内部的application-{profile}.properties或application.yml(带spring.profile)配置文件 **⤴️
-
@Configuration注解类上的@PropertySource ⤴️
-
通过SpringApplication.setDefaultProperties指定的默认属性 ⤴️
或application.yml(不带spring.profile)配置文件** ⤴️ 2. **jar包内部的application.properties或application.yml`(不带spring.profile)配置文件 **⤴️
优先加载带profile
-
jar包外部的application-{profile}.properties或application.yml(带spring.profile)配置文件 ⤴️
-
**jar包内部的application-{profile}.properties或application.yml(带spring.profile)配置文件 **⤴️
-
@Configuration注解类上的@PropertySource ⤴️
-
通过SpringApplication.setDefaultProperties指定的默认属性 ⤴️
所有支持的配置加载来源,请参考官方文档。