Spring Boot配置文件详解:YAML与Properties语法对比及@ConfigurationProperties注解使用
配置文件结构更为清晰,可谓是有其功;然而,也会因那微不足道的空格而破坏层级关系,这又可谓是有其过。本章主要着重介绍 yml 的语法以及从配置文件中取值的相关内容。还在那里干等着什么呢?赶紧来学习吧!

技术包含 yaml 语法、properties 语法,还涉及 ConfigurationProperties 和 Value 注解的使用,以及配置文件占位符的使用。
[id_1783050203]
一、YAML简介
YML 是 YAML(YAML Ain't Markup Language)语言的文件,它是以数据为中心的。并且,它比 json、xml 等更适合用来做配置文件。
yml 与 xml 相比,它少了部分结构化的代码。这样一来,数据就更加直接,能够一目了然。
yml 和 json 怎么样呢?它们没有谁比谁更好,只有合适才是最好的。yml 的语法较为优雅,注释也更标准,所以适合用来做配置文件。而 json 作为一种机器交换格式,在这方面比 yml 更强,更适合用于 api 调用的数据交换。
一)YAML语法
支持三种数据结构,分别是字面值、对象和数组,同时也支持复合结构。
字面值包含字符串、布尔类型、数值以及日期。其中字符串通常是不加引号的,若使用单引号则会对特殊字符进行转义。日期的格式能够支持 yyyy/MM/dd HH:mm:ss 。
对象由键值对构成,键值对的形式为 key: value ,其中冒号后面必须有空格,每组键值对独占一行,并且缩进程度要保持一致,也可以采用行内写法:{k1: v1,....kn: vn}
数组是由形如“- value”的数据构成的。短横线后面必须要有空格,每一组数据都单独占一行,并且缩进程度要相同,还可以用行内写法:[1,2,...n]
复合结构:上面三种数据结构任意组合
二)YAML的运用
创建一个 Spring Boot 的全局配置文件为 application.yml,接着对其进行属性参数的配置。其中包含了多种常用的数据格式,有字符串;有带特殊字符的字符串;有布尔类型;有数值;有集合;有行内集合;有行内对象;还有集合对象。
yaml:
str: 字符串可以不加引号
specialStr: [id_1953969259]
specialStr2: '单引号可以转义\n特殊字符'
flag: false
num: 666
Dnum: 88.88
list:
- one
- two
- two
set: [1,2,2,3] map: {k1: v1, k2: v2} positions:
- name: ITDragon
salary: 15000.00
- name: ITDragonBlog
salary: 18888.88
创建实体类 YamlEntity.java ,然后获取配置文件中的属性值。通过注解@ConfigurationProperties 来获取配置文件中的指定值,并将这些值注入到实体类中。其具体的测试方法以及获取值的原理,需继续往后查看!
import org.springframework.boot.context.properties.ConfigurationProperties;import org.springframework.stereotype.Component;import java.util.List;import java.util.Map;import java.util.Set;/**
* YAML 语法实体类
* 切记点:
* 一、冒号后面加空格,即 key:(空格)value
每行参数左边的空格数量决定了该参数所处的层级,不能胡乱输入。
*/@Component@ConfigurationProperties(prefix = "yaml")public class YamlEntity { // 字面值,字符串,布尔,数值
private String str; // 普通字符串
private String specialStr; // 转义特殊字符串
private String specialStr2;// 输出特殊字符串
private Boolean flag; // 布尔类型
private Integer num; // 整数
private Double dNum; // 小数
数组、List 和 Set 有两种写法。第一种写法是:每个值占一行,需缩进对齐,每个值之间有空格;第二种写法是:[1,2,...n],采用行内写法。
private List<Object> list; // list可重复集合
private Set<Object> set; // set不可重复集合
Map 和实体类有两种写法。第一种写法是:key 空格 value,每个值单独占一行,并且需要进行缩进对齐;第二种写法是:{key: value,...},采用行内写法。
private Map<String, Object> map; // Map K-V
private List<Position> positions; // 复合结构,集合对象
省略了 getter、setter 和 toString 方法。
三)YML小结
字符串可以不使用引号。若使用双引号,会输出特殊字符。若不使用引号或使用单引号,会对特殊字符进行转义。
数组类型,其后面需有空格;对象类型,其后面需有空格。
YAML 是通过空格缩进的程度来对层级关系进行控制的。同时,不能用 tab 键来代替空格,并且它是大小写敏感的。
如何能让一个程序员崩溃呢?在 yml 文件中加入几个空格就可以做到啦!(〃>皿<)
二、Properties简介
大家经常使用 properties 文件,在此简单介绍一下。它的语法结构是这样的:key 等于 value。要注意中文乱码问题,需将其转码成 ASCII 。具体如下:
userinfo.account=itdragonBlog
userinfo.age=25
userinfo.active=true
userinfo.created-date=2018/03/31 16:54:30
userinfo.map.k1=v1
userinfo.map.k2=v2
userinfo.list=one,two,three
userinfo.position.name=Java架构师
userinfo.position.salary=19999.99
从配置文件中取值注入到实体类中,和YAML是一样的。
import org.springframework.boot.context.properties.ConfigurationProperties;import org.springframework.stereotype.Component;import java.util.Date;import java.util.List;import java.util.Map;/**
* 用户信息
* @ConfigurationProperties被修饰类里的所有属性会与配置文件中的指定值进行绑定,这个指定值是通过 prefix 找到的
*/@Component@ConfigurationProperties(prefix = "userinfo")public class UserInfo { private String account; private Integer age; private Boolean active; private Date createdDate; private Map<String, Object> map; private List<Object> list; private Position position; // 省略getter,setter,toString方法}
三、配置文件取值
Spring Boot 借助 ConfigurationProperties 注解从配置文件里获取属性。从上述例子能够明白,ConfigurationProperties 注解能够通过设定 prefix 来明确需要批量导入的数据。它还支持获取字面值、集合、Map、对象等较为复杂的数据。ConfigurationProperties 注解有其他的方面吗?它与 Spring 的 Value 注解存在怎样的差异呢?带着这些疑问,我们接着往下探究。
- 配置的读取和绑定方式相对固定,不够灵活。
ConfigurationProperties注解的优缺点
一、可以从配置文件中批量注入属性;
二、支持获取复杂的数据类型;
三、对属性名匹配的要求不高,像 user-name 、user_name 、userName 以及 USER_NAME 这些情况都能够取到值;
四、支持JAVA的JSR303数据校验;
五、缺点是不支持强大的SpEL表达式;
Value注解的优点和缺点恰好相反。它的一个特点是只能逐个配置注入值。它不具备支持数组、集合等复杂数据类型的能力。它也不支持数据校验。并且对属性名匹配有着严格的要求。而它最大的特点是能够支持 SpEL 表达式,这使得它拥有更丰富的功能。
二)@ConfigurationProperties详解
第一步,需要导入依赖。若要使用 ConfigurationProperties 注解,就需要导入 spring-boot-configuration-processor 这个依赖。
第二步是配置数据。在 application.yml 配置文件里,要配置属性参数,这些参数的前缀是 itdragon,参数包含字面值和数组,通过这些参数可以判断是否具备获取复杂属性的能力。
第三步,进行数据匹配。在类上添加注解 ConfigurationProperties,接着设置 prefix 属性的值为 itdragon,然后将该类添加到 Spring 的 IOC 容器当中。
第四步是校验数据。给数据添加 Validated 注解,然后开启数据校验,接着测试它是否具备支持数据校验的功能。
测试 ConfigurationProperties 注解是否能够支持 SpEL 表达式。
在 pom.xml 中导入依赖,添加 spring-boot-configuration-processor 依赖。
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot 的配置处理器artifactId>
<optional>trueoptional>dependency>
配置数据为 application.yml 的配置属性参数,nick-name 可用于判断匹配属性的松散性,即便将其换成 nick_name ,依然能够获取到值。
itdragon:
nick-name: ITDragonBlog
email: 1234567890@qq.com
iphone: 1234567890
abilities: [java, sql, html] created_date: 2018/03/31 15:27:30
匹配和校验数据:
import org.springframework.boot.context.properties.ConfigurationProperties;import org.springframework.stereotype.Component;import org.springframework.validation.annotation.Validated;import javax.validation.constraints.Email;import java.util.Date;import java.util.List;/**
ConfigurationProperties 注解在语法层面有其特定的表现。
第一步,将 spring-boot-configuration-processor 进行导入。
第二步,将被 ConfigurationProperties 注解修饰的类添加至 Spring 的 IOC 容器内。
* 第三步:设置prefix属性,指定需要注入属性的前缀;
* 第四步:添加数据校验注解,开启数据校验;
*
* 注意点:
nickName 在 yml 配置文件中,其对应参数是中划线;createdDate 在 yml 配置文件中,其对应参数是下划线。这两者用于测试对属性名匹配的松散性。
对 email 进行测试,以验证其对 JSR303 数据校验的支持;对 iphone 进行测试,以验证其对 JSR303 数据校验的支持。
* 三、abilities 测试其支持复杂的数据结构
*/@Component@ConfigurationProperties(prefix = "itdragon")@Validatedpublic class ConfigurationPropertiesEntity { private String nickName; // 解析成功,支持松散匹配属性
private String email;解析失败,数据校验成功:BindValidationException 指出在 itdragon 上存在绑定验证错误。
private String iphone; private List<String> abilities; private Date createdDate; 配置属性的解析为:先计算(1+2-3)/4 的结果,再将该结果乘以 5 。
private String operator; 语法报错,不支持 SpEL 表达式,此情况不适用于该字段。
// 省略getter,setter,toString方法}
三)@Value详解
上一篇博客已经介绍过Value注解的使用,这里只简单说明。
第一步,为属性添加 Value 注解,然后通过${}来设置参数,使其从配置文件中注入值。
第二步,将${itdragon.ceatred_date}里的参数值进行修改,改成${itdragon.ceatredDate},接着测试能否解析成功。
第三步:添加数据校验 Validated 注解。接着开启数据校验。然后测试它是否具备支持数据校验的功能。
第四步:测试Value注解是否支持SpEL表达式;
importSpring 框架的 org.springframework.beans.factory 部分。它在 Spring 应用的开发中起着重要作用,用于创建和管理对象的生命周期等相关操作。这个部分包含了各种用于处理对象创建、依赖注入等方面的类和接口。通过它,开发者可以更方便地管理和操作对象,提高应用的开发效率和可维护性。annotation.Value;importSpring 框架中的@Component 注解用于标识一个类为 Spring 组件;它是 Spring 中用于将类注册为 bean 的一种方式;通过使用@Component 注解,Spring 容器可以自动发现和管理这些被标识的类;这些类可以在应用程序的其他部分被注入和使用。importorg.springframework 在验证领域有所涉及。annotation.Validated;importjavax.validation.constraints 这个包中包含用于验证电子邮件地址的约束,即 Email 约束。import java.util.Date;import java.util.List;/**
* Value 注解语法类
* 第一步:在属性上添加注解Value注入参数
第二步,将被 Value 注解修饰的类添加到 Spring 的 IOC 容器里;
* 第三步:添加数据校验注解,检查是否支持数据校验;
*
* 注意点:
* 一、nickName和createdDate在yml配置文件中,对应参数分别是中划线和下划线,用于测试其对属性名匹配的松散性
* 二、email和iphone 测试其支持JSR303数据校验
* 三、abilities 测试其支持复杂的数据结构
*
* 结论:
createDate 的取值必须与 yml 配置文件中的参数保持相同。
在 iphone 上添加邮箱验证注解后依然能够通过测试。
不支持复杂的数据结构,并且提示的错误与第一条相同,错误为 IllegalArgumentException: 无法解析值 "${itdragon.abilities}" 中的占位符 "itdragon.abilities"
*/@Component@Validatedpublic class ValueEntity { @Value("${itdragon.nick-name}")
private String nickName; @Value("${itdragon.email}")
private String email; @Email
@Value("${itdragon.iphone}") // 解析成功,并不支持数据校验
private String iphone;@Value("${itdragon.abilities}"),此操作存在解析错误,它并不支持复杂的数据结构。
private List abilities;@Value("${itdragon.ceatredDate}"),这里存在解析错误,它并不支持松散匹配属性,而是必须严格保持一致。
private Date createdDate; // Value注解的强大一面:支持SpEL表达式
@Value("#{(1+2-3)/4*5}") // 算术运算
private String operator; @Value("#{1>2 || 2 <= 3}") // 关系运算
private Boolean comparison; @Value(系统属性["java.version"]的值为"#{systemProperties['java.version']}") // 系统配置:os.name
private String systemProperties; @Value(获取 Java 语言中 Math 类的绝对值方法,该方法用于计算给定数值的绝对值,这里计算的是 -18 的绝对值,结果为 18。) // 表达式
private String mapExpression; // 省略getter,setter,toString方法}
四)配置文件取值小结
ConfigurationProperties 注解能够进行批量注入,Value 注解则适宜单个注入。
ConfigurationProperties 注解具备支持数据校验的功能,然而 Value 注解并不具备这一功能。
ConfigurationProperties 注解具备支持松散匹配属性的特点,而 Value 注解则必须要严格匹配属性。
ConfigurationProperties无法支持强大的 SpEL 表达式,然而 Value 是可以支持的;
四、配置文件占位符
占位符和随机数比较简单,这里就直接贴出代码。需要注意的是:
一、占位符的值必须是完整路径
二、占位符设置默认值,冒号后面不能有空格
ran: # 这里的prefix不能是random,
ran-value: ${random.value}
ran-int: ${random.int}
ran-long: ${random.long}
ran-int-num: ${random.int(10)}
ran-int-range: ${random.int[10,20]}
ran-placeholder 的值为 placeholder_${ran.ran-value:此处不能有空格,且 key 为完整路径},它在运行时被赋值。
importSpring 框架中的 Spring Boot 上下文属性相关的类是 ConfigurationProperties 。 它主要用于处理应用程序的配置属性。 该类在 Spring Boot 中起着重要的作用,能够方便地将配置文件中的属性映射到 Java 对象中。 这样可以使应用程序的配置更加灵活和易于管理。 开发人员可以通过该类来定义和绑定应用程序的配置属性,从而实现对应用程序行为的定制化。import org.springframework.stereotype.Component;/**
* 随机数和占位符语法类
*/@Component配置属性的前缀为"ran")public class RandomEntity { private String ranValue; // 随机生成一个字符串
private Integer ranInt; // 随机生成一个整数
private Long ranLong; // 随机生成一个长整数
private Integer ranIntNum; // 在指定范围内随机生成一个整数
private Integer ranIntRange;// 在指定区间内随机生成一个整数
private String ranPlaceholder;// 占位符
省略了 getter、setter 和 toString 方法。
测试代码:
@RunWith(SpringRunner.class)@SpringBootTestpublic class SpringBootYmlApplicationTests { @Autowired
private UserInfo userInfo; @Autowired
private YamlEntity yamlEntity; @Autowired
private ConfigurationPropertiesEntity配置属性实体。@Autowired
private ValueEntity valueEntity; @Autowired
private RandomEntity randomEntity; @Test
public void contextLoads() {// System.out.println("YAML Grammar : " + yamlEntity);// System.out.println("UserInfo : " + userInfo);// System.out.println(ConfigurationProperties 的语法为:配置属性实体;// System.out.println("Value Grammar : " + valueEntity);
System.out.println("Random Grammar : " + randomEntity);
}
}
五、总结
Spring Boot 支持两种格式的配置文件。在这两种格式中,YAML 的数据结构比 properties 更清晰。
二、YAML 是专门用来写配置文件的语言,非常简洁和强大。
三、YAML 对空格的要求很严格,且不能用Tab键代替。
YAML 是通过空格的缩进程度来确定层级的。冒号后面有空格,短横线后面也有空格。
ConfigurationProperties 注解的作用是适合批量注入配置文件中的属性。Value 注解适合获取配置文件中的某一项。
ConfigurationProperties 注解具备支持数据校验以及获取复杂数据的功能,Value 注解则支持 SpEL 表达式。
springboot.springmvc和spring有什么区别 (springboot)
spring框架和springboot spring框架和springmvc框架 (spring festival)
Spring Boot 最外围的 Spring 详解! 大区别 3 和 (springboot)
springboot与spring区别 (springboot框架)
Java中Properties文件的配置与应用:详解test.properties文件格式与使用场景
性能springboot的环境 springboot环境性能 (性能spec)