记一则对SpringBoot@PropertySource不能解

2019-03-22  本文已影响0人  LoWang

scio

https://github.com/rench/scio

起因

在项目中,有一个文件core.yml,里面存储了core模块的一些基础配置,该文件里面的写法有properties的写法也有yaml的写法。例如:

···
scio.core.api.secrets: test,123456
scio.core.sms.appKey=1d5123123165db5
···

在eclipse编辑器中,经常会提示错误,也就是说yml文件中的语法有误。确实,scio.core.sms.appKey=1d5123123165db5这段的写法是properties的写法。但是启动程序,没有任何错误报出,看着不爽,就想把错误取消,所以把scio.core.sms.appKey=1d5123123165db5修改成scio.core.sms.appKey: "1d5123123165db5"。启动项目,junit测试报错了,提示appKey不存在。

发现

发现junit测试错误,根据问题找到校验appKey的业务逻辑,发现${scio.core.sms.appKey}获取到的appKey居然是带有引号的"1d5123123165db5"。那就奇怪了,按照yaml的写法,双引号和单引号只是区分是否转义字符串中的特殊符号,不会把双引号到值里面去的。跟踪发现,core.yml的引用是使用了@PropertySource({"classpath:core.yml"})进行解析的,通过查看@PropertySource注解的解释,如下:Given a file app.properties containing the key/value pair testbean.name=myTestBean, the following @Configuration classuses @PropertySource to contribute app.properties to the Environment's set of PropertySources.,由此可见,默认他是解析的properties文件,猜想,他并没有按照yaml的格式解析,若properties的解析也支持冒号分隔,那么把冒号后面的数据解析带有引号,也就能解释通了。

解析

扩展

package com.scio.cloud.cloudconfig;

import java.io.IOException;
import java.util.Optional;
import java.util.Properties;

import org.springframework.beans.factory.config.YamlPropertiesFactoryBean;
import org.springframework.core.env.PropertiesPropertySource;
import org.springframework.core.env.PropertySource;
import org.springframework.core.io.support.DefaultPropertySourceFactory;
import org.springframework.core.io.support.EncodedResource;
/**
 * CompositePropertySourceFactory support properties and yaml file
 *
 * @author Wang.ch
 * @date 2019-03-22 09:30:15
 */
public class CompositePropertySourceFactory extends DefaultPropertySourceFactory {
  @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);
    }
  }
  /**
   * load yaml file to properties
   *
   * @param resource
   * @return
   * @throws IOException
   */
  private Properties loadYaml(EncodedResource resource) throws IOException {
    YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
    factory.setResources(resource.getResource());
    factory.afterPropertiesSet();
    return factory.getObject();
  }
}
@PropertySource(
    value = {"core.yml", "key.properties"},
    factory = CompositePropertySourceFactory.class)
上一篇下一篇

猜你喜欢

热点阅读