在初始化的项目中有个预置文件application.properties
,这是SpringBoot的配置文件。SpringBoot 默认使用以下 2 种全局的配置文件,其文件名是固定的。
application.properties
:SpringBoot的配置文件,用来修改 Spring Boot 自动配置的默认值,语法机构为:key=value
application.yml
:是一种使用 YAML 语言编写的文件,与 application.properties 一样,可以在 Spring Boot 启动时被自动读取,修改 Spring Boot 自动配置的默认值,简单语法结构为:key:空格 value
大多数情况下我们使用的文件是application.yml
,所以本篇Blog来详细看下YAML配置文件是怎么作用的,如何在SpringBoot中使用。
YAML配置文件
YAML 全称 YAML Ain't Markup Language
(YAML不是一种标记语言),它是一种以数据为中心的标记语言,比 XML 和 JSON 更适合作为配置文件,怎么理解呢?就是这个配置文件的内容单纯的就是数据,通过缩进或者简单的特殊符号标识结构,比XML的一堆标签或者JSON的一堆括号更直接和清晰,例如同样的配置,用xml:
<server> <port>8081<port> </server>
如果用yaml标记:
server: port: 8081
要使用 YAML 作为属性配置文件(以 .yml 或 .yaml 结尾),需将 SnakeYAML 库添加到 classpath 下,Spring Boot 中的 spring-boot-starter-web
或 spring-boot-starter
都对 SnakeYAML 库做了集成, 只要项目中引用了这两个 Starter 中的任何一个,Spring Boot 会自动添加 SnakeYAML 库到 classpath 下。
基本语法
YAML 的基本语法原则有如下两条:
- 使用缩进表示层级关系,缩进时不允许使用 Tab 键,只允许使用空格,空格多少个无所谓只要是左边对齐的一列数据都是同一个层级的
- 属性和值的大小写都十分敏感
只要满足这两条基本的语法,就不会出问题。
常用写法
YAML的常用写法有三种,字面量、对象以及数组,分类进行一下示例
字面量
字面量是指单个的,不可拆分的值,例如:数字、字符串、布尔值、以及日期等,在 YAML 中,使用key:[空格]value
的形式表示一对键值对(空格不能省略)
K: V
字面量直接写在V的位置就可以 , 字符串默认不用加上双引号或者单引号,如果字符串使用了单引号或者双引号对特殊字符的规定如下,例如\n
本身的含义是换行操作
- 双引号,会转义字符串里面的特殊字符 , 特殊字符会作为本身想表示的意思:
name: "田 \n 郭"
,则双引号下转义为换行操作:
田 郭
- 单引号,不会转义特殊字符 , 特殊字符最终会变成和普通字符一样输出,
name: '田 \n 郭'
,则输出为:name: '田 \n 郭'
网上关于转义的操作各种资料存在误解,建议看下译文yaml中该使用引号么
数组
YAML 使用-
表示数组中的元素,普通写法如下:
pets: -dog -cat -pig
行内写法如下:
pets: [dog,cat,pig]
对象
在 YAML 中,对象可能包含多个属性,每一个属性都是一对键值对,普通写法如下:
person: name: tml age: 30
行内写法如下:
person: {name: tml,age: 30}
复合结构
当然我们大多数使用的时候上述三种写法都会用到,复合使用:
person: name: tml age: 30 pets: -dog -cat -pig car: name: 蔚来es6
YAML组织结构
一个 YAML 文件可以由一个或多个文档组成,文档之间使用---
作为分隔符,且各文档相互独立,互不干扰。如果 YAML 文件只包含一个文档,则---
分隔符可以省略。
--- person: name: tml age: 30 pets: -dog -cat -pig car: name: 蔚来es6 --- person: name: gcy age: 30 ---
但是强烈不建议这么做,我们最好把各个文档和文件分开来,结构清晰一些。
SpringBoot配置绑定
yaml文件更强大的地方在于,他可以给我们的实体类直接注入匹配值,也就是我们读取配置再也不用那么麻烦了,还需要写个文件读取类什么的,直接通过注解就可以自动获取,有两种方式:
@ConfigurationProperties
配置yaml自动JavaBean绑定@Value
配置yaml单个属性值绑定@Value
配置外部配置文件属性绑定
接下来通过一个实践来体会下这三种配置绑定方式。
yaml配置绑定实践
首先我们需要编写yaml配置文件和一个外部配置文件,分别看看yaml自动配置绑定和外部配置文件配置绑定方法是什么样的,按照如下结构进行实践:
1 yaml配置及外部properties配置编写
application.yml配置文件内容如下,我们尽量把所有语法都体验下:
person: name: tml age: 30 pets: -dog -cat -pig car: name: 蔚来es6 url: domain: www.baidu.com location: china
application.properties配置文件内容如下:
spring.application.name=springboot
2 配置注入类编写
我们需要编写两个配置注入类,分别是Person和Car
Person.java
package com.example.springboot.model; 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.List; /** * * @Name Person * * @Description * * @author tianmaolin * * @Data 2021/9/27 */ @Component @Data @NoArgsConstructor @AllArgsConstructor @ConfigurationProperties(prefix = "person") @PropertySource(value = "classpath:application.properties") public class Person { //@ConfigurationProperties配置yaml自动JavaBean注入 private String name; private Integer age; private List<String> pets; private Car car; //@Value配置yaml属性引入,SPEL表达式获取值 @Value("${url.domain}") private String url; @Value("${url.location}") private String location; //@Value配置外部配置文件属性绑定 @Value("${spring.application.name}") private String appName; }
Car.java
package com.example.springboot.model; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import org.springframework.stereotype.Component; /** * * @Name Car * * @Description * * @author tianmaolin * * @Data 2021/9/27 */ @Component @Data @NoArgsConstructor @AllArgsConstructor public class Car { private String name; }
3 Controller编写
我们改造下Controller,让返回结果为person的内容
package com.example.springboot.controller; import com.example.springboot.model.Person; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import javax.annotation.Resource; /** * * @Name HelloSpringController * * @Description * * @author tianmaolin * * @Data 2021/9/22 */ @Controller public class HelloSpringController { @Resource private Person person; @ResponseBody @RequestMapping("/hello") public Person hello() { return person; } }
4 打印请求测试
启动服务后我们请求下Controller进行测试,可以发现各项数据都被正确打印了:
@Value和@ConfigurationProperties
@Value 和 @ConfigurationProperties 注解都能读取配置文件中的属性值并绑定到 JavaBean 中,但两者存在以下不同。
- 使用位置不同,@ConfigurationProperties:标注在 JavaBean 的类名上;@Value:标注在 JavaBean 的属性上。
- 功能不同,@ConfigurationProperties:用于批量绑定配置文件中的配置;@Value:只能一个一个的指定需要绑定的配置。
- 松散绑定支持不同,@ConfigurationProperties:支持松散绑定(松散语法),@Vaule:不支持松散绑定。
- SpEL 支持不同,@ConfigurationProperties:不支持 SpEL 表达式;@Value:支持 SpEL 表达式。
- 复杂类型封装,@ConfigurationProperties:支持所有类型数据的封装,例如 Map、List、Set、以及对象等;@Value:只支持基本数据类型的封装,例如字符串、布尔值、整数等类型。
- 应用场景不同,@Value 和 @ConfigurationProperties 两个注解之间,并没有明显的优劣之分,它们只是适合的应用场景不同而已。
若只是获取配置文件中的某项值,则推荐使用 @Value 注解;若专门编写了一个 JavaBean 来和配置文件进行映射,则建议使用 @ConfigurationProperties 注解。我们在选用时,根据实际应用场景选择合适的注解能达到事半功倍的效果。
Spring Boot导入Spring配置
默认情况下,Spring Boot 中是不包含任何的 Spring 配置文件的,即使我们手动添加 Spring 配置文件到项目中,也不会被识别。那么 Spring Boot 项目无法导入 Spring 配置吗?其实Spring Boot
为了我们提供了以下 2 种方式来导入 Spring 配置:
- 使用
@ImportResource
注解加载 Spring 配置文件 - 使用全注解方式加载 Spring 配置
第二种方式使用全注解其实我们之前谈到过【Spring学习笔记 五】Spring注解及Java类配置开发,并且是SpringBoot中最主要的实现方式,另外一种方式可以简单了解下,例如在该项目的 resources 下添加一个名为 beans.xml 的 Spring 配置文件,配置代码如下
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="persionService" class="net.biancheng.www.service.impl.PersonServiceImpl"></bean> </beans>
这样在SpringBoot启动时就会自动将该配置加入了
package com.example.springboot; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.ImportResource; @SpringBootApplication @ImportResource(locations = {"classpath:/beans.xml"}) public class SpringbootApplication { public static void main(String[] args) { SpringApplication.run(SpringbootApplication.class, args); } }
总结一下
yml文件到底是干嘛的终于搞明白了,现在再去看项目中的结构都清晰了很多,知道这些配置是干什么的了,感觉确实yml文件比较好,用对齐来表明结构,可以去掉冗余的文本标记,理解起来更方便了,同时SpringBoot对yml和配置文件的支持也很友好,直接注解注入读取,要知道这要是搁以前得写一个配置类去匹配配置文件的结构再去读取的,多么麻烦啊。