YAML(/ˈjæməl/,尾音类似camel骆驼)是一个可读性高,用来表达数据序列化的格式。YAML参考了其他多种语言,包括:C语言、Python、Perl,并从XML、电子邮件的数据格式(RFC2822)中获得灵感。Clark Evans在2001年首次发表了这种语言,另外Ingy döt Net与OrenBen-Kiki也是这语言的共同设计者。当前已经有数种编程语言或脚本语言支持(或者说解析)这种语言。
官方不推荐properties文件,所以IDEA中项目自动生成的文件直接删除。
建立新的application.yaml文件
语法格式(对空格的要求极其严格):
【父级】
【子级】【空格】【参数】
同时yaml支持配置的同时也可以存对象:
#存对象
student:
name: "jack"
age: 18
#行内形式
student1: {name: "jack",age: 77}
#存数组
list1:
- one
- two
#数组行内写法
list2: [one,two]
yaml甚至可以给实体类赋值:
User对象:
package com.springboot.myweb.pojo;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component
public class User {
private String name;
private String pwd;
public User() {
super();
}
public User(String name, String pwd) {
this.name = name;
this.pwd = pwd;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPwd() {
return pwd;
}
public void setPwd(String pwd) {
this.pwd = pwd;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", pwd='" + pwd + '\'' +
'}';
}
}
Udetil对象:
package com.springboot.myweb.pojo;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.Map;
@Component
public class Udetil {
private String address;
private int age;
private Boolean flag;
private Map<String,Object> maps;
private List<String> lists;
private User user;
public Udetil() {
super();
}
public Udetil(String address, int age, Boolean flag, Map<String, Object> maps, List<String> lists, User user) {
this.address = address;
this.age = age;
this.flag = flag;
this.maps = maps;
this.lists = lists;
this.user = user;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Boolean getFlag() {
return flag;
}
public void setFlag(Boolean flag) {
this.flag = flag;
}
public Map<String, Object> getMaps() {
return maps;
}
public void setMaps(Map<String, Object> maps) {
this.maps = maps;
}
public List<String> getLists() {
return lists;
}
public void setLists(List<String> lists) {
this.lists = lists;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
@Override
public String toString() {
return "Udetil{" +
"address='" + address + '\'' +
", age=" + age +
", flag=" + flag +
", maps=" + maps +
", lists=" + lists +
", user=" + user +
'}';
}
}
yaml配置:
udetil:
address: "小区"
age: 99
flag: false
maps: {key1: v1,k2: v2}
lists: ["aa","bb","cc"]
user:
name: "jack"
pwd: "123123"
ApplicationTests测试类:
package com.springboot.myweb;
import com.springboot.myweb.pojo.Udetil;
import com.springboot.myweb.pojo.User;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import javax.annotation.Resource;
@SpringBootTest
class MywebApplicationTests {
@Resource
private Udetil ud;
@Test
void contextLoads() {
System.out.println(ud);
}
}
当然这样不算完成,如果想要在yaml中对一个类进行赋值,还需要在对应的类上加相关的注解@ConfigurationProperties
,加上后发现爆红,尽管这里的爆红并不影响程序的运行,但若果觉得爆红难受的话可以点上方open
点开后进入浏览器,发现2.3.0版本的找不到,于是倒退版本。
复制依赖:
通过进行配置来产生提示,当然想要生效需要重启IDEA,这里就暂时先不重启了。
接下来需要用该注解绑定到我们yaml中配置的名称:
运行测试,出现结果:
以及我们的yaml中还可以写占位表达。
udetil:
address: ${random.uuid}
age: ${random.int}
flag: false
maps: {key1: v1,k2: v2}
lists: ["aa","bb","cc"]
user:
name: "jack"
pwd: "123123"
访问:
并且yaml可以支持指定多个配置,多个不同的配置块区可以用- - -来区分,使用spring: profiles: 【name】指定名称,spring.profiles.active指定使用
server:
port: 8044
udetil:
address: ${random.uuid}
age: ${random.int}
flag: false
hello: hyyyyyy
maps: {key1: v1,k2: v2}
lists: ["aa","bb","cc"]
user:
name: ${udetil.hello:hello}_jack
pwd: "123123"
#spring.profiles.active用于指定使用哪个模块的配置
spring:
profiles:
active: dev
---
server:
port: 8043
spring:
profiles: dev
---
server:
port: 8045
spring:
profiles: test
则会运行在dev指定的8043端口上:
二:yaml配置原理
文件配置自然是在yaml文件中进行,而yaml中所涉及到的配置非常之多,且有一些配置springboot会默认给加载进去,这里先简单介绍一下这些加载的流程。 因为我们已知springbootApplication注解最终挖取了一个spring.factories的关键文件,该文件中存在大量类似于url之类的东西,可单纯的url是无法完成一个个复杂配置的,因此它背后必然有一个类来替它完成复杂的配置任务,拿常见的webmvc来说,点进去。
接下来我们看到,点进去的配置类中存在一个@Configuration注解将其声明为一个配置类,然后是众多Conditiona开头的注解,这个注解就是在动态的判定项目需不需要引入此类配置,因为刚才我们看到spring.factories文件中存在如此多的配置,而我们的项目并不一定需要将它们全部的加载进去,毕竟我们项目中不需要的配置还要加载进去拿就实数浪费了,而这些Conditiona就是为此而出现的,如果项目不满足这些前置配置条件,那就停止引入配置。
接着我们向下找,有一个资源配置类,点进去。
然后我们就能看到相关的配置信息。
于是我们尝试在yaml文件中书写spring.resources这个参数,可以看到这里出现了一个 addMappings参数。
然后回到我们的properties文件,这个参数恰恰在文件中被定义了。
如果你这里在yaml文件中还配置了端口的信息,当点进去的时候也会发现页面进入到了一个以XXXproperties结尾的配置文件中, 而配置文件中所定义的参数,也正好是我们在yaml文件中能够进行配置的参数。
这也就解释了,为什么我们的项目在不配置端口的时候默认走了8080,因为这些properties文件中已经存在了默认配置,且会被springboot加载并生效,但因为yaml文件级别较高,一旦我们重写了其配置,那项目会优先生效我们自定义的配置。所以说,yaml文件中能够配置的是已经存在了的配置,而这些配置则被具体的定义在了对应的properties文件中,文件最终被配置文件引入,而配置文件又写在了spring.factories文件中,并最终被系统加载。
资料参考:
https://www.thymeleaf.org/doc/tutorials/3.0/usingthymeleaf.htmlhttps://docs.spring.io/spring-boot/docs/2.1.13.RELEASE/reference/html/