SpringBoot绑定复杂类型自定义参数(List/Map/Set/自定义对象等)YML
应用场景
在开发中,我们经常需要把一些随时可能变化的属性配置到配置文件中,这样耦合性低,方便维护。Spring Boot在这方面为我们提供了很大的便捷,我们可以很轻易的将properties
、yml
、yaml
中配置的属性绑定到JAVA实体类上。
具体实施
注意事项
- 您需要保证您需要绑定参数的这个类是被Spring IOC容器所管理的
- 您这个需要绑定参数的类至少需要具有set方法,不然无法绑定(但不会报错,下面演示中使用的lombok提供get、set方法等)
- 您在使用这个类的时候也应该是遵循Spring 依赖注入的规范
代码解释:请看下面的代码:我创建了一个Configuration
类(我使用了Lombok提供get、set方法等),他有一个静态内部类:Properties
,这个内部类我用来作为“配置类出现”,为它绑定属性。所以我用@Component
注解将它交给IOC容器管理,又由于我的Configuration
类需要注入Properties
“配置类”,所以我也将Configuration
类交给了IOC容器管理,在Configuration
中使用@Resource
注解注入了Properties
,而print
方法作为测试方法,我为它加了@PostConstruct
注解(在依注入完成之后自动执行,方便查看测试结果)
package com.scfenzhi.config;import lombok.Data;import org.springframework.boot.context.properties.ConfigurationProperties;import org.springframework.stereotype.Component;import javax.annotation.PostConstruct;import javax.annotation.Resource;/ * @Author: Yi Dai * @Email: 484201132@qq.com * @CreateTime: 2022-01-15 15:51 * @Company: Sichuan Fenzhi International Trade Co., LTD * @Description: */@Componentpublic class Configuration { @Resource private Properties properties; @Data @Component @ConfigurationProperties(prefix = "configuration.properties") private static class Properties { } @PostConstruct public void print() { System.out.println(properties); }}
基本数据类型及字符串类型
Java代码
package com.scfenzhi.config;import lombok.Data;import org.springframework.boot.context.properties.ConfigurationProperties;import org.springframework.stereotype.Component;import javax.annotation.PostConstruct;import javax.annotation.Resource;/ * @Author: DaiYi * @Email: 484201132@qq.com * @CreateTime: 2022-01-15 15:51 * @Company: Sichuan Fenzhi International Trade Co., LTD * @Description: */@Componentpublic class Configuration { @Resource private Properties properties; @Data @Component @ConfigurationProperties(prefix = "configuration.properties") private static class Properties { private byte byteType; private short shortType; private int intType; private long longType; private float floatType; private double doubleType; private boolean booleanType; private char chatType; private String str1; private String str2; private String str3; } @PostConstruct public void print() { System.out.println(properties); }}
yaml代码
configuration: properties: byte-type: 1 short-type: 1 int-type: 1 long-type: 1 float-type: 1.0F double-type: 1.0D boolean-type: true chat-type: 97 str1: haha str2: 'heihei' str3: "xixixi"
输出结果
Configuration.Properties(byteType=1, shortType=1, intType=1, longType=1, floatType=1.0, doubleType=1.0, booleanType=true, chatType=a, str1=haha, str2=heihei, str3=xixixi)
特别注意:
- 绑定char类型时,您可以选择使用字符表码表中的数值来代替字符(比如我上面的
97
就表示字母a
),当然,您也可以使用字面量表示,如chat-type: a
,值您也可以选择用单引号或者双引号包裹起来。这并不会报错。 - 绑定String类型时,您可以选择不用引号或者使用单引号,甚至双引号也可以,都不会报错。在有特殊字符的情况下,使用引号可能是个不错的选择。
- 绑定
boolean
类型参数时,您不仅可以使用true
、false
来表示。您还可以用on
或者off
表示(on=true,off=false) - 绑定
float
类型或者double
类型时,您可以选择在值的后面加一个标识符标识类型,如1.0f
表示这是float
类型,1.0D
表示这是double
类型,大小写均可。但是比较坑的是,long
类型是不能加L
或者l
标识符的,这会报错:
Failed to bind properties under ‘configuration.properties.long-type’ to long:
Property: configuration.properties.long-type
Value: 1L
Origin: class path resource [application.yml] - 89:16
Reason: failed to convert java.lang.String to long (caused by java.lang.NumberFormatException: For input string: “1L”)
对象类型(自定义对象)
Java代码
package com.scfenzhi.config;import lombok.Data;import org.springframework.boot.context.properties.ConfigurationProperties;import org.springframework.stereotype.Component;import javax.annotation.PostConstruct;import javax.annotation.Resource;/ * @Author: Yi Dai * @Email: 484201132@qq.com * @CreateTime: 2022-01-15 15:51 * @Company: Sichuan Fenzhi International Trade Co., LTD * @Description: */@Componentpublic class Configuration { @Resource private Properties properties; @Data @Component @ConfigurationProperties(prefix = "configuration.properties") private static class Properties { private User user; } @Data private static class User { private int id; private String username; private boolean gender; } @PostConstruct public void print() { System.out.println(properties); }}
yaml代码(写法一)
configuration: properties: user: { id: 1001,username: Yi Dai,gender: false }
yaml代码(写法二)
configuration: properties: user: id: 1001 username: Yi Dai gender: on
输出结果
两种写法输出结果一致
Configuration.Properties(user=Configuration.User(id=1001, username=Yi Dai, gender=true))
数组类型
Java代码
package com.scfenzhi.config;import lombok.Data;import org.springframework.boot.context.properties.ConfigurationProperties;import org.springframework.stereotype.Component;import javax.annotation.PostConstruct;import javax.annotation.Resource;/ * @Author: Yi Dai * @Email: 484201132@qq.com * @CreateTime: 2022-01-15 15:51 * @Company: Sichuan Fenzhi International Trade Co., LTD * @Description: */@Componentpublic class Configuration { @Resource private Properties properties; @Data @Component @ConfigurationProperties(prefix = "configuration.properties") private static class Properties { private String[] stringArray; private User[] userArray; } @Data private static class User { private int id; private String username; private boolean gender; } @PostConstruct public void print() { System.out.println(properties); }}
yaml代码(写法一)
configuration: properties: string-array: [ Yi Dai,Guoxu Li ] user-array: [ { id: 1001,username: Yi Dai,password: 123456a,gender: true },{ id: 1002,username: Guoxu Li,password: 123456b,gender: off } ]
yaml代码(写法二)
configuration: properties: string-array: - Yi Dai - Guoxu Li user-array: - id: 1001 username: Yi Dai password: 123456a gender: true - id: 1002 username: Guoxu Li password: 123456b gender: off
输出结果
两种写法输出结果一致
Configuration.Properties(stringArray=[Yi Dai, Guoxu Li], userArray=[Configuration.User(id=1001, username=Yi Dai, gender=true), Configuration.User(id=1002, username=Guoxu Li, gender=false)])
特别注意:
- 在采用写法二绑定数组时,您应该注意每个元素都要换行,且
-
标识符后面应该有一个空格
集合类型
Java代码
package com.scfenzhi.config;import lombok.Data;import lombok.ToString;import org.springframework.boot.context.properties.ConfigurationProperties;import org.springframework.stereotype.Component;import javax.annotation.PostConstruct;import javax.annotation.Resource;import java.util.List;import java.util.Map;import java.util.Set;/ * @Author: DaiYi * @Email: 484201132@qq.com * @CreateTime: 2022-01-15 15:51 * @Company: Sichuan Fenzhi International Trade Co., LTD * @Description: */@ToString@Componentpublic class Configuration { @Resource private Properties properties; @Data @Component @ConfigurationProperties(prefix = "configuration.properties") private static class Properties { private List<String> stringList; private Set<Integer> integerSet; private Map<String, Integer> stringIntegerMap; } @PostConstruct public void print() { System.out.println(properties); }}
yaml代码(写法一)
configuration: properties: string-list: [ YiDai,'Guoxu Li',"Yaxin Zhang" ] integer-set: [ 1,3,5,7,9 ] string-integer-map: { Dai: 18 , "Li": 23,'Zhang': 19 }
yaml代码(写法二)
configuration: properties: string-list: - Yi Dai - 'Guoxu Li' - "Yaxin Zhang" integer-set: - 1 - 3 - 5 - 7 - 9 string-integer-map: Dai: 18 "Li": 23 'Zhang': 19
输出结果
Configuration.Properties(stringList=[YiDai, Guoxu Li, Yaxin Zhang], integerSet=[1, 3, 5, 7, 9], stringIntegerMap={Dai=18, Li=23, Zhang=19})
特别注意:
- 在采用第二种写法绑定map时,您应该注意,此时不是数组了,不能在每一项前面加
-
标识符,如果您加了,这会导致结果的前面多了索引值和一个.
,如:0.Dai=18
。 - 绑定map时(无论何种写法),如果您的key是
String
类型的,那么存在一个问题,就是您多个字符之间的空格会被自动去除(加引号也不好使),但value不会。如果你的key是中文,那么这个键值对将会被忽略 List
集合默认创建java.util.ArrayList
Set
集合默认创建java.util.LinkedHashSet
Map
集合默认创建java.util.LinkedHashMap
复杂类型
Java代码
package com.scfenzhi.config;import lombok.Data;import lombok.ToString;import org.springframework.boot.context.properties.ConfigurationProperties;import org.springframework.stereotype.Component;import javax.annotation.PostConstruct;import javax.annotation.Resource;import java.util.List;import java.util.Map;import java.util.Set;/ * @Author: DaiYi * @Email: 484201132@qq.com * @CreateTime: 2022-01-15 15:51 * @Company: Sichuan Fenzhi International Trade Co., LTD * @Description: */@ToString@Componentpublic class Configuration { @Resource private Properties properties; @Data @Component @ConfigurationProperties(prefix = "configuration.properties") private static class Properties { private User user; private List<User> userList; private Set<User> userSet; private Map<Integer, User> userMap; } @Data private static class User { private Integer id; private String username; private Boolean gender; private Car car; } @Data private static class Car { private Double price; private String brand; } @PostConstruct public void print() { System.out.println(properties); }}
yaml代码(写法一)
configuration: properties: user: { id: 1001, username: Yi Dai,gender: true,car: { price: 1,brand: '宝驴' } } user-list: [ { id: 1001, username: Yi Dai,gender: true,car: { price: 1,brand: '宝驴' } },{ id: 1002, username: Yaxin Zhang,gender: false,car: { price: 2,brand: '玛莎拉驴' } } ] user-set: [ { id: 1001, username: Yi Dai,gender: true,car: { price: 1,brand: '宝驴' } },{ id: 1002, username: Yaxin Zhang,gender: false,car: { price: 2,brand: '玛莎拉驴' } } ] user-map: { 1001: { id: 1001, username: Yi Dai,gender: true,car: { price: 1,brand: '宝驴' } },1002: { id: 1002, username: Yaxin Zhang,gender: false,car: { price: 2,brand: '玛莎拉驴' } } }
yaml代码(写法二)
configuration: properties: user: id: 1001 username: Yi Dai gender: true car: price: 1 brand: 宝驴 user-list: - id: 1001 username: Yi Dai gender: true car: price: 1 brand: 宝驴 - id: 1002 username: Yaxin Zhang gender: false car: price: 1 brand: 玛莎拉驴 user-set: - id: 1001 username: Yi Dai gender: true car: price: 1 brand: 宝驴 - id: 1002 username: Yaxin Zhang gender: false car: price: 1 brand: 玛莎拉驴 user-map: 1001: id: 1001 username: Yi Dai gender: true car: price: 1 brand: 宝驴 1002: id: 1002 username: Yaxin Zhang gender: false car: price: 1 brand: 玛莎拉驴
输出结果
两种方式都能正常绑定
Configuration.Properties(user=Configuration.User(id=1001, username=Yi Dai, gender=true, car=Configuration.Car(price=1.0, brand=宝驴)), userList=[Configuration.User(id=1001, username=Yi Dai, gender=true, car=Configuration.Car(price=1.0, brand=宝驴)), Configuration.User(id=1002, username=Yaxin Zhang, gender=false, car=Configuration.Car(price=2.0, brand=玛莎拉驴))], userSet=[Configuration.User(id=1001, username=Yi Dai, gender=true, car=Configuration.Car(price=1.0, brand=宝驴)), Configuration.User(id=1002, username=Yaxin Zhang, gender=false, car=Configuration.Car(price=2.0, brand=玛莎拉驴))], userMap={1001=Configuration.User(id=1001, username=Yi Dai, gender=true, car=Configuration.Car(price=1.0, brand=宝驴)), 1002=Configuration.User(id=1002, username=Yaxin Zhang, gender=false, car=Configuration.Car(price=2.0, brand=玛莎拉驴))})
其他细节
- 由于是松散绑定,所以您可以选择将属性名之间的多个单词的分割符改为下划线(
_
)