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

应用场景

在开发中,我们经常需要把一些随时可能变化的属性配置到配置文件中,这样耦合性低,方便维护。Spring Boot在这方面为我们提供了很大的便捷,我们可以很轻易的将propertiesymlyaml中配置的属性绑定到JAVA实体类上。
SpringBoot绑定复杂类型自定义参数(List/Map/Set/自定义对象等)YML

具体实施

*注意事项

  • 您需要保证您需要绑定参数的这个类是被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:
 */

@Component
public 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:
 */

@Component
public 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:
 */

@Component
public 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:
 */

@Component
public 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
@Component
public 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不会。
  • 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
@Component
public 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=玛莎拉驴))})

其他细节

  • 由于是松散绑定,所以您可以选择将属性名之间的多个单词的分割符改为下划线(_)
上一篇:05、Netty学习笔记—(案例:聊天业务)


下一篇:scaffold-dbcontext 命令使用说明