> 文档中心 > SpringBoot绑定复杂类型自定义参数(List/Map/Set/自定义对象等)YML

SpringBoot绑定复杂类型自定义参数(List/Map/Set/自定义对象等)YML


应用场景

在开发中,我们经常需要把一些随时可能变化的属性配置到配置文件中,这样耦合性低,方便维护。Spring Boot在这方面为我们提供了很大的便捷,我们可以很轻易的将propertiesymlyaml中配置的属性绑定到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类型参数时,您不仅可以使用truefalse来表示。您还可以用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=玛莎拉驴))})

其他细节

  • 由于是松散绑定,所以您可以选择将属性名之间的多个单词的分割符改为下划线(_)