Spring Boot配置文件详解

  Spring Boot提供了两种常用的配置文件,分别是properties文件和yml文件。

一、yml配置方式

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

  创建一个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获取配置文件中的指定值并注入到实体类中。

  1 import org.springframework.boot.context.properties.ConfigurationProperties;
  2 import org.springframework.stereotype.Component;
  3 
  4 import java.util.List;
  5 import java.util.Map;
  6 import java.util.Set;
  7 
  8 /**
  9  * YAML 语法实体类
 10  *
 11  * 切记点:
 12  * 一、冒号后面加空格,即 key:(空格)value
 13  * 二、每行参数左边空格数量决定了该参数的层级,不可乱输入。
 14  */
 15 
 16 @Component
 17 @ConfigurationProperties(prefix = "yaml")
 18 public class YamlEntity {
 19 
 20     // 字面值,字符串,布尔,数值
 21     private String str; // 普通字符串
 22     private String specialStr; // 输出特殊字符串
 23     private String specialStr2;// 转义特殊字符串
 24     private Boolean flag;   // 布尔类型
 25     private Integer num;    // 整数
 26     private Double dNum;    // 小数
 27 
 28     // 数组,List和Set,两种写法: 第一种:-空格value,每个值占一行,需缩进对齐;第二种:[1,2,...n] 行内写法
 29     private List<Object> list;  // list可重复集合
 30     private Set<Object> set;    // set不可重复集合
 31 
 32     // Map和实体类,两种写法:第一种:key空格value,每个值占一行,需缩进对齐;第二种:{key: value,....} 行内写法
 33     private Map<String, Object> map; // Map K-V
 34     private List<Position> positions;  // 复合结构,集合对象
 35 
 36     public String getStr() {
 37         return str;
 38     }
 39 
 40     public void setStr(String str) {
 41         this.str = str;
 42     }
 43 
 44     public String getSpecialStr() {
 45         return specialStr;
 46     }
 47 
 48     public void setSpecialStr(String specialStr) {
 49         this.specialStr = specialStr;
 50     }
 51 
 52     public String getSpecialStr2() {
 53         return specialStr2;
 54     }
 55 
 56     public void setSpecialStr2(String specialStr2) {
 57         this.specialStr2 = specialStr2;
 58     }
 59 
 60     public Boolean getFlag() {
 61         return flag;
 62     }
 63 
 64     public void setFlag(Boolean flag) {
 65         this.flag = flag;
 66     }
 67 
 68     public Integer getNum() {
 69         return num;
 70     }
 71 
 72     public void setNum(Integer num) {
 73         this.num = num;
 74     }
 75 
 76     public Double getdNum() {
 77         return dNum;
 78     }
 79 
 80     public void setdNum(Double dNum) {
 81         this.dNum = dNum;
 82     }
 83 
 84     public List<Object> getList() {
 85         return list;
 86     }
 87 
 88     public void setList(List<Object> list) {
 89         this.list = list;
 90     }
 91 
 92     public Set<Object> getSet() {
 93         return set;
 94     }
 95 
 96     public void setSet(Set<Object> set) {
 97         this.set = set;
 98     }
 99 
100     public Map<String, Object> getMap() {
101         return map;
102     }
103 
104     public void setMap(Map<String, Object> map) {
105         this.map = map;
106     }
107 
108     public List<Position> getPositions() {
109         return positions;
110     }
111 
112     public void setPositions(List<Position> positions) {
113         this.positions = positions;
114     }
115 
116     @Override
117     public String toString() {
118         return "YamlEntity{" +
119                 "str='" + str + '\'' +
120                 ", specialStr='" + specialStr + '\'' +
121                 ", specialStr2='" + specialStr2 + '\'' +
122                 ", flag=" + flag +
123                 ", num=" + num +
124                 ", dNum=" + dNum +
125                 ", list=" + list +
126                 ", set=" + set +
127                 ", map=" + map +
128                 ", positions=" + positions +
129                 '}';
130     }
131 }

测试用例在最下面。

二、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\u67B6\u6784\u5E08(Java架构师)
userinfo.position.salary=19999.99

  从配置文件中取值注入到实体类中,和YAML是一样的。

 1 package com.itdragon.entity;
 2 
 3 import org.springframework.boot.context.properties.ConfigurationProperties;
 4 import org.springframework.stereotype.Component;
 5 
 6 import java.util.Date;
 7 import java.util.List;
 8 import java.util.Map;
 9 
10 /**
11  * 用户信息
12  * @ConfigurationProperties : 被修饰类中的所有属性会和配置文件中的指定值(该值通过prefix找到)进行绑定
13  */
14 @Component
15 @ConfigurationProperties(prefix = "userinfo")
16 public class UserInfo {
17 
18     private String account;
19     private Integer age;
20     private Boolean active;
21     private Date createdDate;
22     private Map<String, Object> map;
23     private List<Object> list;
24     private Position position;
25 
26     public String getAccount() {
27         return account;
28     }
29 
30     public void setAccount(String account) {
31         this.account = account;
32     }
33 
34     public Integer getAge() {
35         return age;
36     }
37 
38     public void setAge(Integer age) {
39         this.age = age;
40     }
41 
42     public Boolean getActive() {
43         return active;
44     }
45 
46     public void setActive(Boolean active) {
47         this.active = active;
48     }
49 
50     public Date getCreatedDate() {
51         return createdDate;
52     }
53 
54     public void setCreatedDate(Date createdDate) {
55         this.createdDate = createdDate;
56     }
57 
58     public Map<String, Object> getMap() {
59         return map;
60     }
61 
62     public void setMap(Map<String, Object> map) {
63         this.map = map;
64     }
65 
66     public List<Object> getList() {
67         return list;
68     }
69 
70     public void setList(List<Object> list) {
71         this.list = list;
72     }
73 
74     public Position getPosition() {
75         return position;
76     }
77 
78     public void setPosition(Position position) {
79         this.position = position;
80     }
81 
82     @Override
83     public String toString() {
84         return "UserInfo{" +
85                 "account='" + account + '\'' +
86                 ", age=" + age +
87                 ", active=" + active +
88                 ", createdDate=" + createdDate +
89                 ", map=" + map +
90                 ", list=" + list +
91                 ", position=" + position +
92                 '}';
93     }
94 }

  测试用例在最下面。

三、配置文件取值对比

一)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

匹配和校验数据:

 1 package com.itdragon.entity;
 2 
 3 import org.springframework.boot.context.properties.ConfigurationProperties;
 4 import org.springframework.stereotype.Component;
 5 import org.springframework.validation.annotation.Validated;
 6 
 7 import javax.validation.constraints.Email;
 8 import java.util.Date;
 9 import java.util.List;
10 
11 /**
12  * ConfigurationProperties 注解语法类
13  * 第一步:导入依赖 spring-boot-configuration-processor;
14  * 第二步:把ConfigurationProperties注解修饰的类添加到Spring的IOC容器中;
15  * 第三步:设置prefix属性,指定需要注入属性的前缀;
16  * 第四步:添加数据校验注解,开启数据校验;
17  *
18  * 注意点:
19  * 一、nickName和createdDate在yml配置文件中,对应参数分别是中划线和下划线,用于测试其对属性名匹配的松散性
20  * 二、email和iphone 测试其支持JSR303数据校验
21  * 三、abilities 测试其支持复杂的数据结构
22  *
23  * 若想运行成功,需要注释33行
24  */
25 
26 @Component
27 @ConfigurationProperties(prefix = "itdragon")
28 @Validated
29 public class ConfigurationPropertiesEntity {
30 
31     private String nickName;    // 解析成功,支持松散匹配属性
32     private String email;
33 //    @Email                      // 解析失败,数据校验成功:BindValidationException: Binding validation errors on itdragon
34     private String iphone;
35     private List<String> abilities;
36     private Date createdDate;   // 解析成功,支持松散匹配属性
37 
38 //    @ConfigurationProperties("#{(1+2-3)/4*5}")
39     private String operator;    // 语法报错,不支持SpEL表达式:not applicable to field
40 
41     public String getNickName() {
42         return nickName;
43     }
44 
45     public void setNickName(String nickName) {
46         this.nickName = nickName;
47     }
48 
49     public String getEmail() {
50         return email;
51     }
52 
53     public void setEmail(String email) {
54         this.email = email;
55     }
56 
57     public String getIphone() {
58         return iphone;
59     }
60 
61     public void setIphone(String iphone) {
62         this.iphone = iphone;
63     }
64 
65     public List<String> getAbilities() {
66         return abilities;
67     }
68 
69     public void setAbilities(List<String> abilities) {
70         this.abilities = abilities;
71     }
72 
73     public Date getCreatedDate() {
74         return createdDate;
75     }
76 
77     public void setCreatedDate(Date createdDate) {
78         this.createdDate = createdDate;
79     }
80 
81     @Override
82     public String toString() {
83         return "ConfigurationPropertiesEntity{" +
84                 "nickName='" + nickName + '\'' +
85                 ", email='" + email + '\'' +
86                 ", iphone='" + iphone + '\'' +
87                 ", abilities=" + abilities +
88                 ", createdDate=" + createdDate +
89                 '}';
90     }
91 }

三)@Value详解

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

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

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

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

  1 package com.itdragon.entity;
  2 
  3 import org.springframework.beans.factory.annotation.Value;
  4 import org.springframework.stereotype.Component;
  5 import org.springframework.validation.annotation.Validated;
  6 
  7 import javax.validation.constraints.Email;
  8 import java.util.Date;
  9 import java.util.List;
 10 
 11 /**
 12  * Value 注解语法类
 13  * 第一步:在属性上添加注解Value注入参数
 14  * 第二步:把Value注解修饰的类添加到Spring的IOC容器中;
 15  * 第三步:添加数据校验注解,检查是否支持数据校验;
 16  *
 17  * 注意点:
 18  * 一、nickName和createdDate在yml配置文件中,对应参数分别是中划线和下划线,用于测试其对属性名匹配的松散性
 19  * 二、email和iphone 测试其支持JSR303数据校验
 20  * 三、abilities 测试其支持复杂的数据结构
 21  *
 22  * 结论:
 23  * 一、createDate取值必须和yml配置文件中的参数保持一致,
 24  * 二、既是在iphone上添加邮箱验证注解依然可以通过测试,
 25  * 三、不支持复杂的数据结构,提示错误和第一条相同:IllegalArgumentException: Could not resolve placeholder 'itdragon.abilities' in value "${itdragon.abilities}"
 26  *
 27  * 若想运行成功,需要注释42行;修改44行,将ceatredDate修改为ceatred_date
 28  */
 29 
 30 @Component
 31 @Validated
 32 public class ValueEntity {
 33 
 34     @Value("${itdragon.nick-name}")
 35     private String nickName;
 36     @Value("${itdragon.email}")
 37     private String email;
 38     @Email
 39     @Value("${itdragon.iphone}")        // 解析成功,并不支持数据校验
 40     private String iphone;
 41 //    @Value("${itdragon.abilities}")     // 解析错误,并不支持复杂的数据结构
 42     private List<String> abilities;
 43 //    @Value("${itdragon.ceatredDate}")   // 解析错误,并不支持松散匹配属性,必须严格一致
 44     private Date createdDate;
 45 
 46     // Value注解的强大一面:支持SpEL表达式
 47     @Value("#{(1+2-3)/4*5}")            // 算术运算
 48     private String operator;
 49     @Value("#{1>2 || 2 <= 3}")          // 关系运算
 50     private Boolean comparison;
 51     @Value("#{systemProperties['java.version']}") // 系统配置:os.name
 52     private String systemProperties;
 53     @Value("#{T(java.lang.Math).abs(-18)}") // 表达式
 54     private String mapExpression;
 55 
 56     public String getNickName() {
 57         return nickName;
 58     }
 59 
 60     public void setNickName(String nickName) {
 61         this.nickName = nickName;
 62     }
 63 
 64     public String getEmail() {
 65         return email;
 66     }
 67 
 68     public void setEmail(String email) {
 69         this.email = email;
 70     }
 71 
 72     public String getIphone() {
 73         return iphone;
 74     }
 75 
 76     public void setIphone(String iphone) {
 77         this.iphone = iphone;
 78     }
 79 
 80     public List<String> getAbilities() {
 81         return abilities;
 82     }
 83 
 84     public void setAbilities(List<String> abilities) {
 85         this.abilities = abilities;
 86     }
 87 
 88     public Date getCreatedDate() {
 89         return createdDate;
 90     }
 91 
 92     public void setCreatedDate(Date createdDate) {
 93         this.createdDate = createdDate;
 94     }
 95 
 96     public String getOperator() {
 97         return operator;
 98     }
 99 
100     public void setOperator(String operator) {
101         this.operator = operator;
102     }
103 
104     public Boolean getComparison() {
105         return comparison;
106     }
107 
108     public void setComparison(Boolean comparison) {
109         this.comparison = comparison;
110     }
111 
112     public String getSystemProperties() {
113         return systemProperties;
114     }
115 
116     public void setSystemProperties(String systemProperties) {
117         this.systemProperties = systemProperties;
118     }
119 
120     public String getMapExpression() {
121         return mapExpression;
122     }
123 
124     public void setMapExpression(String mapExpression) {
125         this.mapExpression = mapExpression;
126     }
127 
128     @Override
129     public String toString() {
130         return "ValueEntity{" +
131                 "nickName='" + nickName + '\'' +
132                 ", email='" + email + '\'' +
133                 ", iphone='" + iphone + '\'' +
134                 ", abilities=" + abilities +
135                 ", createdDate=" + createdDate +
136                 ", operator='" + operator + '\'' +
137                 ", comparison=" + comparison +
138                 ", systemProperties='" + systemProperties + '\'' +
139                 ", mapExpression='" + mapExpression + '\'' +
140                 '}';
141     }
142 }

四)配置文件取值小结

一、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为完整路径}
 1 package com.itdragon.entity;
 2 
 3 import org.springframework.boot.context.properties.ConfigurationProperties;
 4 import org.springframework.stereotype.Component;
 5 
 6 /**
 7  * 随机数和占位符语法类
 8  */
 9 
10 @Component
11 @ConfigurationProperties(prefix = "ran")
12 public class RandomEntity {
13 
14     private String ranValue;    // 随机生成一个字符串
15     private Integer ranInt;     // 随机生成一个整数
16     private Long ranLong;       // 随机生成一个长整数
17     private Integer ranIntNum;  // 在指定范围内随机生成一个整数
18     private Integer ranIntRange;// 在指定区间内随机生成一个整数
19     private String ranPlaceholder;// 占位符
20 
21     public String getRanValue() {
22         return ranValue;
23     }
24 
25     public void setRanValue(String ranValue) {
26         this.ranValue = ranValue;
27     }
28 
29     public Integer getRanInt() {
30         return ranInt;
31     }
32 
33     public void setRanInt(Integer ranInt) {
34         this.ranInt = ranInt;
35     }
36 
37     public Long getRanLong() {
38         return ranLong;
39     }
40 
41     public void setRanLong(Long ranLong) {
42         this.ranLong = ranLong;
43     }
44 
45     public Integer getRanIntNum() {
46         return ranIntNum;
47     }
48 
49     public void setRanIntNum(Integer ranIntNum) {
50         this.ranIntNum = ranIntNum;
51     }
52 
53     public Integer getRanIntRange() {
54         return ranIntRange;
55     }
56 
57     public void setRanIntRange(Integer ranIntRange) {
58         this.ranIntRange = ranIntRange;
59     }
60 
61     public String getRanPlaceholder() {
62         return ranPlaceholder;
63     }
64 
65     public void setRanPlaceholder(String ranPlaceholder) {
66         this.ranPlaceholder = ranPlaceholder;
67     }
68 
69     @Override
70     public String toString() {
71         return "RandomEntity{" +
72                 "ranValue='" + ranValue + '\'' +
73                 ", ranInt=" + ranInt +
74                 ", ranLong=" + ranLong +
75                 ", ranIntNum=" + ranIntNum +
76                 ", ranIntRange=" + ranIntRange +
77                 ", ranPlaceholder='" + ranPlaceholder + '\'' +
78                 '}';
79     }
80 }

测试代码:

 1 package com.itdragon.yml;
 2 
 3 import com.itdragon.entity.*;
 4 import org.junit.Test;
 5 import org.junit.runner.RunWith;
 6 import org.springframework.beans.factory.annotation.Autowired;
 7 import org.springframework.boot.test.context.SpringBootTest;
 8 import org.springframework.test.context.junit4.SpringRunner;
 9 
10 @RunWith(SpringRunner.class)
11 @SpringBootTest
12 public class SpringBootYmlApplicationTests {
13 
14     @Autowired
15     private UserInfo userInfo;
16 
17     @Autowired
18     private YamlEntity yamlEntity;
19 
20     @Autowired
21     private ConfigurationPropertiesEntity configurationPropertiesEntity;
22 
23     @Autowired
24     private ValueEntity valueEntity;
25 
26     @Autowired
27     private RandomEntity randomEntity;
28 
29     @Test
30     public void contextLoads() {
31         System.out.println("YAML Grammar : " + yamlEntity);
32 //        System.out.println("UserInfo : " + userInfo);
33 //        System.out.println("ConfigurationProperties Grammar : " + configurationPropertiesEntity);
34 //        System.out.println("Value Grammar : " + valueEntity);
35 //        System.out.println("Random Grammar : " + randomEntity);
36     }
37 
38 }

原文链接:https://www.cnblogs.com/itdragon/p/8686554.html

posted @ 2018-12-01 10:02  梨花梦蝶  阅读(380)  评论(0编辑  收藏  举报