【SpringBoot框架学习】yml/yaml语法 详解
基本知识点:
什么是yml/yaml?:
YAML是 "YAML Ain't a Markup Language" (YAML不是一种标记语言)的 递归缩写
在开发的这种语言时,YAML 的意思其实是:
"Yet Another Markup Language"(仍是一种标记语言)
这种语言以数据作为中心,而不是以标记语言为重点!
为什么要使用yml/yaml来进行开发?
优点:
- 语法要简单,灵活
- 能够写注释
- 能够比较方便的覆盖参数值(方便书写或者debug)
- 能够重用配置片段,
比较大一点的project中,
经常有很多地方的配置需要保持一致,
最好的办法就是引入变量和引用的概念- 可以继承
基本语法:
八大基本类型 + 字符串:
格式:
目标成员名: 普通的值
注意:
- 字符串默认不用加上双引号或者单引号
- '' (单引号):
不会 转义 字符串里面的特殊字符 ,
特殊字符最终会变成和普通字符一样输出比如:msg: 'hello \n spring boot'
输出:hello \n spring boot
- "" (双引号):
会转义特殊字符 ,
特殊字符会作为本身想表示的意思比如:
msg: "hello \n spring boot"
则会 输出 :hello 换行 spring boot
对象:
格式:
目标对象名:
对象的成员1: 1成员的值
对象的成员2: 2成员的值
...
Map(双列集合):
格式:
目标map的名称:
key1: value1
key2: value2
...
数组(List、Set 等单列集合):
格式:
目标单列集合名:
- 集合中的值1
- 集合中的值2
- 集合中的值3
- ...
或
目标单列集合名: [集合中的值1, 集合中的值2, 集合中的值3, ...]
注意点:
- :(冒号)后的空格不能省略
- 以缩进来控制层级关系,
只要是左边对齐的一列数据都是同一个层级的- 属性和值的大小写都是十分敏感的
属性的注入:
在本人之前的博文中曾讲到过:
配置文件 的 目的 是:
将配置文件中的值注入给代码中 需要的地方
在SpringBoot中,提供了相关的注解,来注入相应的值:
@ConfigurationProperties注解:
作用:
一般都是配合该注解的 prefix属性,
来指定要进行注入的 配置的值
注意:
- prefix属性的值,为配置文件中的 要赋值的段落名
- 实体类中要被赋值的成员名,要与 配置文件中的对应段落名 一致
例如:
pet:
name: "吉吉国王"
yell: "呜~"
package edu.youzg.demo.model;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* @Author: Youzg
* @CreateTime: 2020-06-17 15:17
* @Description: 带你深究Java的本质!
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@ConfigurationProperties(prefix = "pet")
@Component
public class Pet {
private String name;
private String yell;
}
随机数 的生成:
格式:
${random.随机数的类型}
而上述的 随机数类型,总共分为 4种:
分类:
- int(可设置上限值)
- long(可设置上限值)
- uuid(随机字符串,更不容易 重复)
- value(随机字符串)
例如:
id: ${random.uuid} # value int long
@ConfigurationProperties注解 作为 springBoot 所提供的属性注入注解,
也提供了一些非常强大的功能,其中最常用的就是 松散绑定:
松散绑定:
定义:
yml/yaml配置文件 中 配置 的 键名为 xx_xx形式
实体类 的 成员名 为 驼峰式
也可进行注入
例如:
myFan:
the_pets:
- name: "加菲"
yell: "喵~"
@Data
@NoArgsConstructor
@AllArgsConstructor
@Component
@ConfigurationProperties(prefix = "myFan")
public class Fan {
private List<Pet> thePets;
}
讲到 属性的注入问题,有的同学可能就会想到:
当初学习spring Framework的时候,所使用的 @Value注解
那么,现在本人就来讲解下 @ConfigurationProperties注解 和 @Value注解 之间的 区别 以及 各自的应用场景:
@ConfigurationProperties注解 与 @Value注解:
首先本人来列举下这两个注解的区别:
区别:
比较项目 | @ConfigurationProperties | @Value |
---|---|---|
功能 | 批量注入 配置文件中的属性 | 一个个指定注入 配置文件中的属性 |
松散绑定 | 支持 | 不支持 |
SpEL | 不支持 | 支持 |
JSR303校验 | 支持 | 不支持 |
复杂封装类型 | 支持 | 不支持 |
那么,区别这么多,这两个注解的应用场景是什么呢?
应用场景:
- @Value注解:
只是在某个业务逻辑中需要获取一下配置文件中的某项值- @ConfigurationProperties注解:
专门编写了一个JavaBean来和配置文件进行映射
在有些情况下,我们不希望application配置文件中的属性配置太过繁琐
需要将有些属性的配置放到其它的配置文件中去
那么,针对这种需求,springBoot提供了 @PropertySource注解:
注入 其它配置文件的属性 —— @PropertySource注解:
例如:
首先,本人来提供一个 pet.properties配置文件:
pet.name=killer queen
pet.yell=wryyyyyyyyy
接下来,我们来修改下 Pet类 的 内容:
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;
@Data
@AllArgsConstructor
@NoArgsConstructor
@PropertySource({"classpath:pet.properties"}) // 指定要被 “额外加载” 的配置文件的 全路径名
@ConfigurationProperties(prefix = "pet") // 指定前缀
@Component
public class Pet {
private String name;
private String yell;
}
那么,我们来做个小测试:
import edu.youzg.entity.Pet;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class ProfileDemoApplicationTests {
@Autowired
private Pet myPet;
@Test
public void myTest() {
System.out.println(myPet);
}
}
运行结果:
多配置文件 问题:
在有的大型项目中,我们或许能够看到 这样的情况:
一个项目,配置了多个配置文件(即:配置了多个application.yml)
配置文件 优先级:
springBoot提供了 四个 可以 放置配置文件 的 位置:
- file: ./config(项目路径下的config文件夹配置文件)
- file: ./(项目路径下配置文件)
- classpath: /config(资源路径下的config文件夹配置文件)
- classpath: /(资源路径下配置文件)
如下图所示:
指定 开发环境:
在我们今后的工作中,可能会遇到这样的情况:
在测试开发时,操作的是一些数据库
在产品发布时,使用的是另一些数据库
那么,这样的话,我们就需要配置多套配置文件,操作起来比较麻烦
因此,spring Boot 提供了切换开发环境的功能:
核心操作:
在application-default.yml文件中,增加如下代码:
spring:
profiles:
active: 指定的配置文件的“后缀名”
例如:
首先,我们需要一个默认的配置文件:
其 文件名 必须为:application-default.yml(或 application-default.properties):
server:
port: 8085
spring:
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/dbstudy?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=UTF-8
username: root
password: 123456
devtools:
restart:
log-condition-evaluation-delta: true
exclude: static/css/**, static/js/**
thymeleaf:
cache: false
prefix: classpath:/templates/views/
suffix: .html
# 指定开发环境(指定配置文件中 没配置则填充,配置了则覆盖)
profiles:
active: dev
#mapper-locations 映射所在的路径
#给模型的包起个别名
mybatis:
mapper-locations: classpath:/mapper/*Mapper.xml
type-aliases-package: edu.youzg.about_boot.model
#打印日志 SQL 执行
logging:
level:
edu:
youzg:
about_boot:
mapper: debug
(本例 主要是 配置port,以及 指定了环境的配置)
之后,本人再来给出 开发环境 和 产品环境 的配置文件:
application-dev.yml:
server:
port: 8100
application-prod.yml:
server:
port: 8090
那么,当我们再次运行时,控制台就会显示如下结果:
可以看到:端口号变为了我们指定的端口
多配置文件 的合并:
若是我们想要在激活一个配置文件同时激活多个配置,
就需要在目标开发环境中,加入
spring:
profiles:
include:
- 指定的配置文件的“后缀名1”
- 指定的配置文件的“后缀名2”,
- ...
(注意:若重名,include中的值会覆盖 原配置文件的值)
但是,如上的多开发环境也可以在一个配置文件中实现:
单配置文件 配置 多开发环境:
核心步骤:
将每个 子开发环境 放在主开发环境下,
并使用
---
分隔开,
再通过
spring:
profiles:
active: 指定的配置文件的“后缀名”
来指定
例子:
server:
port: 8080
spring:
profiles:
active: test
---
spring:
profiles: test
server:
port: 9000
---
spring:
profiles: production
server:
port: 9050
那么,当我们运行之后,控制台就会显示如下结果:
使用展示:
本人先来给出一个宠物类:
package edu.youzg.demo.model;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* @Author: Youzg
* @CreateTime: 2020-06-17 15:17
* @Description: 带你深究Java的本质!
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@ConfigurationProperties(prefix = "pet")
@Component
public class Pet {
private String name;
private String yell;
}
接下来,本人给出一个 粉丝类:
package edu.youzg.demo.model;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import java.util.Date;
import java.util.List;
/**
* @Author: Youzg
* @CreateTime: 2020-06-17 15:13
* @Description: 带你深究Java的本质!
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
@Component
@ConfigurationProperties(prefix = "myFan")
public class Fan {
private String name;
private String id;
private Date birthday;
private Integer age;
private List<Pet> thePets;
}
对应的 yml配置文件:
myFan:
name: "右转哥的小迷妹"
id: ${random.uuid} # value int long
birthday: 2020/6/18
the_pets:
- name: "加菲"
yell: "喵~"
- name: "史努比"
yell: "汪~"
最后是 测试类:
package edu.youzg.demo;
import edu.youzg.demo.model.Fan;
import edu.youzg.demo.model.Pet;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class DemoApplicationTests {
@Autowired
private Fan fan;
@Test
void contextLoads() {
System.out.println(fan);
}
}
现在,本人来展示下运行结果:
可以看到:
本人没有配置age成员的值,
因此,除了age成员为null,其余成员的值都为配置文件中所配置的值