Spring Boot 配置文件详解

Spring Boot配置文件详解

Spring Boot提供了两种经常使用的配置文件,分别是properties文件和yml文件。他们的做用都是修改Spring Boot自动配置的默认值。相对于properties文件而言,yml文件更年轻,也有不少的坑。可谓成也萧何败也萧何,yml经过空格来肯定层级关系,使配置文件结构更清晰,但也会由于微不足道的空格而破坏了层级关系。本章重点介绍yml的语法和从配置文件中取值。还在等什么,赶快来学习吧!html

技术:yaml、properties语法,ConfigurationProperties和Value注解的使用,配置文件占位符的使用java

说明:本章重点介绍yaml的语法和ConfigurationProperties注解的使用,测试代码和完整代码请移步github,喜欢的朋友能够点个star。git

源码:https://github.com/ITDragonBlog/daydayup/tree/master/SpringBoot/spring-boot-yml程序员

文章目录结构:
806956-20180401220714608-87698899.pnggithub

1、YAML简介

yml是YAML(YAML Ain't Markup Language)语言的文件,以数据为中心,比json、xml等更适合作配置文件spring

yml和xml相比,少了一些结构化的代码,使数据更直接,一目了然。sql

yml和json呢?没有谁好谁坏,合适才是最好的。yml的语法比json优雅,注释更标准,适合作配置文件。json做为一种机器交换格式比yml强,更适合作api调用的数据交换。json

一)YAML语法

以空格的缩进程度来控制层级关系。空格的个数并不重要,只要左边空格对齐则视为同一个层级。注意不能用tab代替空格。且大小写敏感。支持字面值,对象,数组三种数据结构,也支持复合结构。api

字面值:字符串,布尔类型,数值,日期。字符串默认不加引号,单引号会转义特殊字符。日期格式支持yyyy/MM/dd HH:mm:ss数组

对象:由键值对组成,形如 key:(空格)value 的数据组成。冒号后面的空格是必需要有的,每组键值对占用一行,且缩进的程度要一致,也可使用行内写法:{k1: v1, ....kn: vn}

数组:由形如 -(空格)value 的数据组成。短横线后面的空格是必需要有的,每组数据占用一行,且缩进的程度要一致,也可使用行内写法: [1,2,...n]

复合结构:上面三种数据结构任意组合

二)YAML的运用

建立一个Spring Boot 的全局配置文件 application.yml,配置属性参数。主要有字符串,带特殊字符的字符串,布尔类型,数值,集合,行内集合,行内对象,集合对象这几种经常使用的数据格式。

yaml:
  str: 字符串能够不加引号
  specialStr: "双引号直接输出\n特殊字符"
  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 语法实体类 * 切记点: * 1、冒号后面加空格,即 key:(空格)value * 2、每行参数左边空格数量决定了该参数的层级,不可乱输入。 */ @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,两种写法: 第一种:-空格value,每一个值占一行,需缩进对齐;第二种:[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方法 }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 语法实体类 * 切记点: * 1、冒号后面加空格,即 key:(空格)value * 2、每行参数左边空格数量决定了该参数的层级,不可乱输入。 */ @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,两种写法: 第一种:-空格value,每一个值占一行,需缩进对齐;第二种:[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小结

1、字符串能够不加引号,若加双引号则输出特殊字符,若不加或加单引号则转义特殊字符;

2、数组类型,短横线后面要有空格;对象类型,冒号后面要有空格;

3、YAML是以空格缩进的程度来控制层级关系,但不能用tab键代替空格,大小写敏感;

4、如何让一个程序员崩溃?在yml文件中加几个空格!(〃>皿<)

2、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方法 }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方法 }

3、配置文件取值

Spring Boot经过ConfigurationProperties注解从配置文件中获取属性。从上面的例子能够看出ConfigurationProperties注解能够经过设置prefix指定须要批量导入的数据。支持获取字面值,集合,Map,对象等复杂数据。ConfigurationProperties注解还有其余特么呢?它和Spring的Value注解又有什么区别呢?带着这些问题,咱们继续往下看。(๑•̀ㅂ•́)و✧

一)ConfigurationProperties和Value优缺点

ConfigurationProperties注解的优缺点

1、能够从配置文件中批量注入属性;

2、支持获取复杂的数据类型;

3、对属性名匹配的要求较低,好比user-name,user_name,userName,USER_NAME均可以取值;

4、支持JAVA的JSR303数据校验;

5、缺点是不支持强大的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.boot</groupId>
  <artifactId>spring-boot-configuration-processor</artifactId>
  <optional>true</optional>
</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属性,指定须要注入属性的前缀; * 第四步:添加数据校验注解,开启数据校验; * * 注意点: * 1、nickName和createdDate在yml配置文件中,对应参数分别是中划线和下划线,用于测试其对属性名匹配的松散性 * 2、email和iphone 测试其支持JSR303数据校验 * 3、abilities 测试其支持复杂的数据结构 */ @Component @ConfigurationProperties(prefix = "itdragon") @Validated public class ConfigurationPropertiesEntity { private String nickName; // 解析成功,支持松散匹配属性 private String email; // @Email // 解析失败,数据校验成功:BindValidationException: Binding validation errors on itdragon private String iphone; private List<String> abilities; private Date createdDate; // 解析成功,支持松散匹配属性 // @ConfigurationProperties("#{(1+2-3)/4*5}") private String operator; // 语法报错,不支持SpEL表达式:not applicable to field // 省略getter,setter,toString方法 }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属性,指定须要注入属性的前缀; * 第四步:添加数据校验注解,开启数据校验; * * 注意点: * 1、nickName和createdDate在yml配置文件中,对应参数分别是中划线和下划线,用于测试其对属性名匹配的松散性 * 2、email和iphone 测试其支持JSR303数据校验 * 3、abilities 测试其支持复杂的数据结构 */ @Component @ConfigurationProperties(prefix = "itdragon") @Validated public class ConfigurationPropertiesEntity { private String nickName; // 解析成功,支持松散匹配属性 private String email; // @Email // 解析失败,数据校验成功:BindValidationException: Binding validation errors on itdragon private String iphone; private List<String> abilities; private Date createdDate; // 解析成功,支持松散匹配属性 // @ConfigurationProperties("#{(1+2-3)/4*5}") private String operator; // 语法报错,不支持SpEL表达式:not applicable to field // 省略getter,setter,toString方法 }

三)@Value详解

上一篇博客已经介绍过Value注解的使用,这里只简单说明。

第一步:在属性上添加Value注解,经过${}设置参数从配置文件中注入值;

第二步:修改${itdragon.ceatred_date}中的参数值,改成${itdragon.ceatredDate}测试是否能解析成功;

第三步:添加数据校验Validated注解,开启数据校验,测试其是否支持数据校验的功能;

第四步:测试Value注解是否支持SpEL表达式;

import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import org.springframework.validation.annotation.Validated; import javax.validation.constraints.Email; import java.util.Date; import java.util.List; /** * Value 注解语法类 * 第一步:在属性上添加注解Value注入参数 * 第二步:把Value注解修饰的类添加到Spring的IOC容器中; * 第三步:添加数据校验注解,检查是否支持数据校验; * * 注意点: * 1、nickName和createdDate在yml配置文件中,对应参数分别是中划线和下划线,用于测试其对属性名匹配的松散性 * 2、email和iphone 测试其支持JSR303数据校验 * 3、abilities 测试其支持复杂的数据结构 * * 结论: * 1、createDate取值必须和yml配置文件中的参数保持一致, * 2、既是在iphone上添加邮箱验证注解依然能够经过测试, * 3、不支持复杂的数据结构,提示错误和第一条相同:IllegalArgumentException: Could not resolve placeholder 'itdragon.abilities' in value "${itdragon.abilities}" */ @Component @Validated public 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<String> 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("#{systemProperties['java.version']}") // 系统配置:os.name private String systemProperties; @Value("#{T(java.lang.Math).abs(-18)}") // 表达式 private String mapExpression; // 省略getter,setter,toString方法 }import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import org.springframework.validation.annotation.Validated; import javax.validation.constraints.Email; import java.util.Date; import java.util.List; /** * Value 注解语法类 * 第一步:在属性上添加注解Value注入参数 * 第二步:把Value注解修饰的类添加到Spring的IOC容器中; * 第三步:添加数据校验注解,检查是否支持数据校验; * * 注意点: * 1、nickName和createdDate在yml配置文件中,对应参数分别是中划线和下划线,用于测试其对属性名匹配的松散性 * 2、email和iphone 测试其支持JSR303数据校验 * 3、abilities 测试其支持复杂的数据结构 * * 结论: * 1、createDate取值必须和yml配置文件中的参数保持一致, * 2、既是在iphone上添加邮箱验证注解依然能够经过测试, * 3、不支持复杂的数据结构,提示错误和第一条相同:IllegalArgumentException: Could not resolve placeholder 'itdragon.abilities' in value "${itdragon.abilities}" */ @Component @Validated public 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<String> 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("#{systemProperties['java.version']}") // 系统配置:os.name private String systemProperties; @Value("#{T(java.lang.Math).abs(-18)}") // 表达式 private String mapExpression; // 省略getter,setter,toString方法 }

四)配置文件取值小结

1、ConfigurationProperties注解支持批量注入,而Value注解适合单个注入;

2、ConfigurationProperties注解支持数据校验,而Value注解不支持;

3、ConfigurationProperties注解支持松散匹配属性,而Value注解必须严格匹配属性;

4、ConfigurationProperties不支持强大的SpEL表达式,而Value支持;

4、配置文件占位符

占位符和随机数比较简单,这里就直接贴出代码。须要注意的是:

1、占位符的值必须是完整路径

2、占位符设置默认值,冒号后面不能有空格

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为完整路径}
import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; /** * 随机数和占位符语法类 */ @Component @ConfigurationProperties(prefix = "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方法e }import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; /** * 随机数和占位符语法类 */ @Component @ConfigurationProperties(prefix = "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方法e }

测试代码:

@RunWith(SpringRunner.class) @SpringBootTest public class SpringBootYmlApplicationTests { @Autowired private UserInfo userInfo; @Autowired private YamlEntity yamlEntity; @Autowired private ConfigurationPropertiesEntity 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 Grammar : " + configurationPropertiesEntity); // System.out.println("Value Grammar : " + valueEntity); System.out.println("Random Grammar : " + randomEntity); } }@RunWith(SpringRunner.class) @SpringBootTest public class SpringBootYmlApplicationTests { @Autowired private UserInfo userInfo; @Autowired private YamlEntity yamlEntity; @Autowired private ConfigurationPropertiesEntity 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 Grammar : " + configurationPropertiesEntity); // System.out.println("Value Grammar : " + valueEntity); System.out.println("Random Grammar : " + randomEntity); } }

5、总结

1、Spring Boot 支持两种格式的配置文件,其中YAML的数据结构比properties更清晰。

2、YAML 是专门用来写配置文件的语言,很是简洁和强大。

3、YAML 对空格的要求很严格,且不能用Tab键代替。

4、YAML 经过空格缩进的程度肯定层级,冒号后面有空格,短横线后面有空格。

5、ConfigurationProperties注解适合批量注入配置文件中的属性,Value注解适合获取配置文件中的某一项。

6、ConfigurationProperties注解支持数据校验和获取复杂的数据,Value注解支持SpEL表达式。

文章到这里就结束了。若是文章对你有帮助,能够点个"推荐",也能够"关注"我,得到更多丰富的知识。

这里是博客文章目录一栏表中的部份内容,若是有感兴趣的内容能够点击右边的连接: http://www.cnblogs.com/itdragon/p/8709948.html

文章目录