Spring Boot 配置文件详解
Spring Boot 配置文件详解
Spring Boot 提供了两种常用的配置文件,分别是 properties 文件和 yml 文件。他们的作用都是修改 Spring Boot 自动配置的默认值。相对于 properties 文件而言,yml 文件更年轻,也有很多的坑。可谓成也萧何败也萧何,yml 通过空格来确定层级关系,使配置文件结构更清晰,但也会因为微不足道的空格而破坏了层级关系。本章重点介绍 yml 的语法和从配置文件中取值。还在等什么,赶快来学习吧!
技术:yaml、properties 语法,ConfigurationProperties 和 Value 注解的使用,配置文件占位符的使用
说明:本章重点介绍 yaml 的语法和 ConfigurationProperties 注解的使用,测试代码和完整代码请移步 github,喜欢的朋友可以点个 star。
源码:https://github.com/ITDragonBlog/daydayup/tree/master/SpringBoot/spring-boot-yml
文章目录结构:
一、YAML 简介
yml 是 YAML(YAML Ain't Markup Language)语言的文件,以数据为中心,比 json、xml 等更适合做配置文件
yml 和 xml 相比,少了一些结构化的代码,使数据更直接,一目了然。
yml 和 json 呢?没有谁好谁坏,合适才是最好的。yml 的语法比 json 优雅,注释更标准,适合做配置文件。json 作为一种机器交换格式比 yml 强,更适合做 api 调用的数据交换。
一)YAML 语法
以空格的缩进程度来控制层级关系。空格的个数并不重要,只要左边空格对齐则视为同一个层级。注意不能用 tab 代替空格。且大小写敏感。支持字面值,对象,数组三种数据结构,也支持复合结构。
字面值:字符串,布尔类型,数值,日期。字符串默认不加引号,单引号会转义特殊字符。日期格式支持 yyyy/MM/dd HH🇲🇲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 语法实体类
* 切记点:
* 一、冒号后面加空格,即 key:(空格)value
* 二、每行参数左边空格数量决定了该参数的层级,不可乱输入。
*/
@Component
@ConfigurationProperties(prefix = "yaml")
public class YamlEntity {
<span class="hljs-comment">// 字面值,字符串,布尔,数值</span>
<span class="hljs-keyword">private</span> String str; <span class="hljs-comment">// 普通字符串</span>
<span class="hljs-keyword">private</span> String specialStr; <span class="hljs-comment">// 转义特殊字符串</span>
<span class="hljs-keyword">private</span> String specialStr2;<span class="hljs-comment">// 输出特殊字符串</span>
<span class="hljs-keyword">private</span> Boolean flag; <span class="hljs-comment">// 布尔类型</span>
<span class="hljs-keyword">private</span> Integer num; <span class="hljs-comment">// 整数</span>
<span class="hljs-keyword">private</span> Double dNum; <span class="hljs-comment">// 小数</span>
<span class="hljs-comment">// 数组,List和Set,两种写法: 第一种:-空格value,每个值占一行,需缩进对齐;第二种:[1,2,...n] 行内写法</span>
<span class="hljs-keyword">private</span> List<Object> list; <span class="hljs-comment">// list可重复集合</span>
<span class="hljs-keyword">private</span> Set<Object> set; <span class="hljs-comment">// set不可重复集合</span>
<span class="hljs-comment">// Map和实体类,两种写法:第一种:key空格value,每个值占一行,需缩进对齐;第二种:{key: value,....} 行内写法</span>
<span class="hljs-keyword">private</span> Map<String, Object> map; <span class="hljs-comment">// Map K-V</span>
<span class="hljs-keyword">private</span> List<Position> positions; <span class="hljs-comment">// 复合结构,集合对象</span>
<span class="hljs-comment">// 省略getter,setter,toString方法</span>
}
三)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 {
<span class="hljs-keyword">private</span> String account;
<span class="hljs-keyword">private</span> Integer age;
<span class="hljs-keyword">private</span> Boolean active;
<span class="hljs-keyword">private</span> Date createdDate;
<span class="hljs-keyword">private</span> Map<String, Object> map;
<span class="hljs-keyword">private</span> List<Object> list;
<span class="hljs-keyword">private</span> Position position;
// 省略 getter,setter,toString 方法
}
三、配置文件取值
Spring Boot 通过 ConfigurationProperties 注解从配置文件中获取属性。从上面的例子可以看出 ConfigurationProperties 注解可以通过设置 prefix 指定需要批量导入的数据。支持获取字面值,集合,Map,对象等复杂数据。ConfigurationProperties 注解还有其他特么呢?它和 Spring 的 Value 注解又有什么区别呢?带着这些问题,我们继续往下看。(๑•̀ㅂ•́)و✧
一)ConfigurationProperties 和 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.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 属性,指定需要注入属性的前缀;
* 第四步:添加数据校验注解,开启数据校验;
*
* 注意点:
* 一、nickName 和 createdDate 在 yml 配置文件中,对应参数分别是中划线和下划线,用于测试其对属性名匹配的松散性
* 二、email 和 iphone 测试其支持 JSR303 数据校验
* 三、abilities 测试其支持复杂的数据结构
*/
@Component
@ConfigurationProperties(prefix = "itdragon")
@Validated
public class ConfigurationPropertiesEntity {
<span class="hljs-keyword">private</span> String nickName; <span class="hljs-comment">// 解析成功,支持松散匹配属性</span>
<span class="hljs-keyword">private</span> 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
<span class="hljs-comment">// 省略getter,setter,toString方法</span>
}
三)@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 容器中;
* 第三步:添加数据校验注解,检查是否支持数据校验;
*
* 注意点:
* 一、nickName 和 createdDate 在 yml 配置文件中,对应参数分别是中划线和下划线,用于测试其对属性名匹配的松散性
* 二、email 和 iphone 测试其支持 JSR303 数据校验
* 三、abilities 测试其支持复杂的数据结构
*
* 结论:
* 一、createDate 取值必须和 yml 配置文件中的参数保持一致,
* 二、既是在 iphone 上添加邮箱验证注解依然可以通过测试,
* 三、不支持复杂的数据结构,提示错误和第一条相同:IllegalArgumentException: Could not resolve placeholder 'itdragon.abilities' in value "${itdragon.abilities}"
*/
@Component
@Validated
public class ValueEntity {
<span class="hljs-meta">@Value("${itdragon.nick-name}")</span>
<span class="hljs-keyword">private</span> String nickName;
<span class="hljs-meta">@Value("${itdragon.email}")</span>
<span class="hljs-keyword">private</span> String email;
<span class="hljs-meta">@Email</span>
<span class="hljs-meta">@Value("${itdragon.iphone}")</span> <span class="hljs-comment">// 解析成功,并不支持数据校验</span>
<span class="hljs-keyword">private</span> String iphone;
// @Value("${itdragon.abilities}") // 解析错误,并不支持复杂的数据结构
private List<String> abilities;
// @Value("${itdragon.ceatredDate}") // 解析错误,并不支持松散匹配属性,必须严格一致
private Date createdDate;
<span class="hljs-comment">// Value注解的强大一面:支持SpEL表达式</span>
<span class="hljs-meta">@Value("#{(1+2-3)/4*5}")</span> <span class="hljs-comment">// 算术运算</span>
<span class="hljs-keyword">private</span> String operator;
<span class="hljs-meta">@Value("#{1>2 || 2 <= 3}")</span> <span class="hljs-comment">// 关系运算</span>
<span class="hljs-keyword">private</span> Boolean comparison;
<span class="hljs-meta">@Value("#{systemProperties['java.version']}")</span> <span class="hljs-comment">// 系统配置:os.name</span>
<span class="hljs-keyword">private</span> String systemProperties;
<span class="hljs-meta">@Value("#{T(java.lang.Math).abs(-18)}")</span> <span class="hljs-comment">// 表达式</span>
<span class="hljs-keyword">private</span> String mapExpression;
<span class="hljs-comment">// 省略getter,setter,toString方法</span>
}
四)配置文件取值小结
一、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 为完整路径}
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
随机数和占位符语法类
*/
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 {
<span class="hljs-meta">@Autowired</span>
<span class="hljs-keyword">private</span> UserInfo userInfo;
<span class="hljs-meta">@Autowired</span>
<span class="hljs-keyword">private</span> YamlEntity yamlEntity;
<span class="hljs-meta">@Autowired</span>
<span class="hljs-keyword">private</span> ConfigurationPropertiesEntity configurationPropertiesEntity;
<span class="hljs-meta">@Autowired</span>
<span class="hljs-keyword">private</span> ValueEntity valueEntity;
<span class="hljs-meta">@Autowired</span>
<span class="hljs-keyword">private</span> RandomEntity randomEntity;
<span class="hljs-meta">@Test</span>
<span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">contextLoads</span><span class="hljs-params">()</span> {
// 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);
}
}
五、总结
一、Spring Boot 支持两种格式的配置文件,其中 YAML 的数据结构比 properties 更清晰。
二、YAML 是专门用来写配置文件的语言,非常简洁和强大。
三、YAML 对空格的要求很严格,且不能用 Tab 键代替。
四、YAML 通过空格缩进的程度确定层级,冒号后面有空格,短横线后面有空格。
五、ConfigurationProperties 注解适合批量注入配置文件中的属性,Value 注解适合获取配置文件中的某一项。
六、ConfigurationProperties 注解支持数据校验和获取复杂的数据,Value 注解支持 SpEL 表达式。
扩展链接:
Sort 坑爹的字符串排序
文章到这里就结束了。如果文章对你有帮助,可以点个 "推荐",也可以"关注" 我,获得更多丰富的知识。
这里是博客文章目录一栏表中的部分内容,如果有感兴趣的内容可以点击右边的链接: http://www.cnblogs.com/itdragon/p/8709948.html