SpringBoot读取Properties和Yaml文件

1 序

SpringBoot.jpg
  • 示例代码(maven分支,load-properties模块):https://gitee.com/eugene-example/springboot
  • 首先,我们通常读取的配置文件是指propertiesyaml两类。无论是使用Maven还是Gradle工具来构建,我们读取都是基于类路径,也就是工程resources目录下存放的文件。本文先讲解读取properties类型的配置文件。
  • SpringBoot配置文件,例如工程resources目录下存放的:bootstrap.propertiesapplication.propertiesapplication-dev.propertiesapplication-prod.properties
  • 用户自定义的配置文件,例如工程resources目录下存放的:config.propertiesdb/ds.properties
  • Spring Framework相关注解说明:
    • @PropertySource注解,使用value属性,来指定加载类路径下的properties文件,读取SpringBoot配置文件时无需使用此注解,直接通过@Value注解读取即可。
    • @Value注解,通过表达式${key.key...}直接读取SpringBoot配置文件的属性。或者结合@ConfigurationProperties注解使用。同时也可使用表达式#{object.prop}来读取对象属性。
    • @ConfigurationProperties注解,使用prefix属性指定读取属性的前缀,可配合@Value注解使用,便于简化读取属性表达式。

2 示例展示

2.1 使用的示例文件

  • SpringBoot配置文件:resource\application.properties,内容如下:
server.port=9999
  • 类路径下的用户自定义配置文件:resource\config.properties,内容如下:
user.name=EugeneHeen
user.password=12345678
  • 类路径下自定义目录存放的用户自定义配置文件:resource\db\ds.yml,内容如下:
ds:
  driver-class-name: com.mysql.cj.jdbc.Driver
  url: jdbc:mysql://127.0.0.1:3306/eugene
  username: root
  password: 88888888
  pool:
    name: ds-poll
    select: SELECT 1 FROM A

2.2 读取SpringBoot规范的默认配置文件

  1. 通过定义一个POJO封装SpringBoot配置文件的属性读取
@Data // 通过Lombok提供GET和SET方法
@ConfigurationProperties(prefix = "server")
@Component
public class BootProps {
    private Integer port;
}

@RestController
@RequestMapping("/boots")
public class BootController {

    @Autowired
    private BootProps bootProps;

    @Value("${server.port}")
    private String port;

    @GetMapping("/auth")
    public String auth() {
        return new StringBuilder("SpringBoot Server Port")
                .append(": ")
                .append(this.port)
                .append(", 通过封装Bean获取Port:")
                .append(this.bootProps.getPort()).toString();
    }
}
  1. 直接在使用的类中通过@Value注解标记示例变量读取,例如,ControllerService
@RestController
@RequestMapping("/configs")
public class BootController {
    @Value("${server.port}")
    private Integer port;
    
    @GetMapping("/value")
    public String value() {
        return new StringBuilder("SpringBoot Server Port")
                .append(": ")
                .append(this.port).toString();
     }
 }

2.3 读取用户自定义的配置文件

  1. 通过定义一个POJO类 ,@PropertySource + @Value注解来读取
@Data
@PropertySource(value = {"config.properties"})
@Component
public class ConfigProps {
    @Value("${user.name}")
    private String name;
    @Value("${user.password}")
    private String password;
}
  • 通过定义一个POJO类 ,@PropertySource + @ConfigurationProperties注解来简化读取,也可配合@Value注解使用。这种方法对YAML文件无效,后续会通过详细示例阐述如何解决此问题
@Data
@PropertySource(value = {"db/ds.properties"})
@ConfigurationProperties(prefix = "master")
@Component
public class DsProps {
    private String username;

    private String password;
}

经实际测试,SpringBoot2.3+的版本,会自动将配置文件中的单词-连接的属性,同自定义POJO类中遵循驼峰命名的属性匹配,无需使用@Value注解来完成值读取。例如,1. 配置文件username自动对应POJO类中的userName属性。2. 配置文件driver-class-name自动对应POJO类中的driverClassName属性。

3 读取用户自定义YAML文件

3.1 User Define YAML,SpringBoot Say No!我不支持下面这些骚操作

  1. @PropertySource + @Value注解
  2. @PropertySource + @ConfigurationProperties注解

Tip:@PropertySource不支持YAML文件加载,它仅仅支持Properties文件加载

3.2 单层级YAML配置文件读取

  1. 单层级 VS 多层级
    • 但层级配置文件
      ds:
          driver-class-name: com.mysql.cj.jdbc.Driver
          url: jdbc:mysql://127.0.0.1:3306/eugene
          username: root
          password: 88888888
      
    • 多层级配置文件
      ds:
          driver-class-name: com.mysql.cj.jdbc.Driver
          url: jdbc:mysql://127.0.0.1:3306/eugene
          username: root
          password: 88888888
          pool:
              name: ds-poll
              select: SELECT 1 FROM A
      
  2. 通过定义一个POJO类 ,@PropertySource + @ConfigurationProperties + @Value注解来实现单层级YAML配置文件读取
@Data
@PropertySource(value = {"db/ds.yml"})
@ConfigurationProperties(prefix = "ds")
@Component
public class DsYaml {
    @Value("${driver-class-name}")
    private String driverClassName;

    @Value("${username}")
    private String userName;

    @Value("${password}")
    private String password;
}

3.3 多层级YAML配置文件读取

  1. User Define YAML,SpringBoot Only Supports!我仅支持唯一的骚操作

    • @PropertySource指定factory属性为自定义DefaultPropertySourceFactory的扩展类 + @Value注解(别再瞎搞!切记!此处无法再使用@ConfigurationProperties注解的prefix属性指定前缀了)
  2. 关于Spring Framework中与配置文件相关的3个类:

    • YamlPropertiesFactoryBean:用于将YAML文件加载为Properties文件。
    • YamlMapFactoryBean:用于将YAML文件加载为Map对象。
    • DefaultPropertySourceFactory@PropertySource注解中的factory属性默认使用的实现类。
  3. 扩展DefaultPropertySourceFactory类,自定义YAML文件加载工厂类

public class YamlPropertySourceFactory extends DefaultPropertySourceFactory {
    public YamlPropertySourceFactory() {
        super();
    }

    @Override
    public PropertySource createPropertySource(String name, EncodedResource resource) throws IOException {
        String sourceName = Optional.ofNullable(name).orElse(resource.getResource().getFilename());
        if (!resource.getResource().exists()) {
            // return an empty Properties
            return new PropertiesPropertySource(sourceName, new Properties());
        } else if (sourceName.endsWith(".yml") || sourceName.endsWith(".yaml")) {
            Properties propertiesFromYaml = loadYaml(resource);
            return new PropertiesPropertySource(sourceName, propertiesFromYaml);
        } else {
            return super.createPropertySource(name, resource);
        }
    }

    /**
     * 加载YAML文件
     * @param resource YAML文件
     * @return Properties对象
     * @throws IOException 文件加载异常
     */
    private Properties loadYaml(EncodedResource resource) throws IOException {
        YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
        factory.setResources(resource.getResource());
        factory.afterPropertiesSet();
        return factory.getObject();
    }
}
  1. 加载多层级YAML配置文件
@Data
@PropertySource(factory = YamlPropertySourceFactory.class, value = {"db/ds.yml"})
@Component
public class DsAYaml {
    @Value("${ds.driver-class-name}")
    private String driverClassName;

    @Value("${ds.username}")
    private String userName;

    @Value("${ds.password}")
    private String password;

    @Value("${ds.pool.name}")
    private String poolName;

    @Value("${ds.pool.select}")
    private String poolSelect;
}

你可能感兴趣的:(SpringBoot读取Properties和Yaml文件)