什么是 yaml
YAML 是 “YAML Ain’t Markup Language” (YAML不是一种标记语言)的递归缩写。在开发的这种语言时,YAML的意思其实是 “Yet Another Markup Language”(仍是一种标记语言)。
yaml 基本语法
key: value; kv 之间有空格大小写敏感
使用缩进表示层级关系
缩进不允许使用 tab,只允许空格
缩进的空格数不重要,只要相同层级的元素左对齐即可
‘#‘ 表示注释
”与” 表示字符串内容会被转义/不转义
yaml 数据类型
字面量
单个的,不可再分的值。date、boolean、string、number、null 。
k: v
对象
键值对集合。map、hash、set、object
# 行内写法
k: {k1: v1, k2: v2, k3: v3}
# 或者这样子
k:
k1: v1
k2: v2
k3: v3
数组
一组按次序排列的值。array、list、queue
# 行内写法
k: [v1, v2, v3]
# 或者这样子
k:
- v1
- v2
- v3
读取 yaml 的配置文件
和之前读取 properties 配置文件一样,通过 ConfigurationProperties 注解来将配置文件中的配置项加载到配置类中。
两个配置类
以下有两个 java 代码,分别是用户类和宠物类。这是用户类
@ConfigurationProperties(prefix = "person")
@Component
@Data
public class Person {
private String userName;
private Boolean boss;
private Date birth;
private Integer age;
private Pet pet;
private String[] interests;
private List<String> animal;
private Map<String, Object> score;
private Set<Double> salarys;
private Map<String, List<Pet>> allPets;
}
这是宠物类
@Data
public class Pet {
private String name;
private Double weight;
}
对应的 yaml 写法
参照上面的基本语法和数据类型,大致就能够写出来对应的 yaml 配置。
person:
userName: 小赫赫
boss: true
birth: 2019/01/01
age: 23
pet:
name: 柯基
weight: 30.12
interests:
- bilibili
- acgn
- running
- coding
animal:
- pig
- cat
- dog
- chicken
- duck
score:
java: 100
webui: 99
math: 95
salarys:
- 1000.0
- 999.98
- 999.99
allPets:
cat:
- name: tomcat
weight: 30
- name: xixi
weight: 10
- name: heihei
weight: 20
dog:
- name: tomdog
weight: 30
- name: xiaoqiang
weight: 40
遇到的疑问
Q1:为什么 interests 、animal 、salarys 这三个写法都是一样的呢?
interests 对应 java 配置类中的属性 interests ,其类型是 String 数组类型。而 animal 类型对应的是 List 集合类型。这两者其实没什么区别,因为 List 集合底层很有可能是数组(也有可能是以链表的形式),所以我认为是没什么区别的。
而 salary 就有区别了,它是集合类型,集合中的元素是不能重复的。所以我们可以测试测试。
我在 animal 中再添加一个 dog
animal:
- pig
- cat
- dog
- chicken
- duck
- dog
我在 salarys 中再添加一个相同的薪资
salarys:
- 1000.0
- 999.98
- 999.99
- 999.99
得到的结果如下。可以看出,虽然写法一样,但是展示的效果还是取决于配置类中的数据类型是怎样的。
比如 Map 集合是用 kv 来表示的,其实实体类也是可以用 kv 来表示的。
Q2:为什么用 2019-01-01 会转换异常?
在我测试的时候,需要在实体类上配置 @DateTimeFormat 注解,要我们自己来将日期来格式化。它默认的格式为 yyyy/MM/dd HH:mm:ss
。
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date birth;
Q3:我听说 yaml 中的字符串类型,字符串两端可以不加单引号或者双引号,也可以加,那我觉得没啥区别呀。是不是没什么用呀?
我觉得有用,而且是非常有用。单引号和双引号的区别可以决定将转义字符将其转义,比如,我们可以测试一下,这里有一个 yaml 的配置文件,比如我们将字符串将其用单引号包裹起来会是怎么样的。
person:
userName: '小赫赫\n大潮吧'
在控制台输出的运行结果如下,可知,使用单引号之后,字符串转义字符的转义功能失效了,直接将 \n
当成字符串打印了。
小赫赫\n大潮吧
如果我将单引号换成双引号,那么它将出现什么样的情况呢?
person:
userName: "小赫赫\n大潮吧"
在控制台输出的运行结果如下,可知,使用双引号之后,字符串的转义字符的功能是正常的了,所以就换行了。
小赫赫
大潮吧
那我不加呢?不加就和使用单引号一样。
自定义配置类的提示
如果要让我们的自定义的配置类生效,那么非常简单,只需要引入下面的依赖就好了。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
然后,将项目进行重新运行一下,可以看到这里有我们自定义的配置类的提示。但是请看 person.user-name
这个属性,之前我们写的时候是 person.userName
是这样的。其实提示上的写法也是可以的。因为 yaml 会将大写的字字母给变成为 -小写字母
的形式。
除此之外,这个配置类的提示的依赖,似乎在运行的时候起不到任何所用,只在开发的使用才有用。所以可以这样将这个依赖在打包时排除。
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<excludes>
<exclude>
<groupId>org.springframework.boot</groupId>
<artifactId>sprng-boot-configuration- processor</artifactId>
</exclude>
</excludes>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
当然,不排除也是可以的。只不过会占用几百 k 的空间大小而已。
请勿发布违反中国大陆地区法律的言论,请勿人身攻击、谩骂、侮辱和煽动式的语言。