前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >[Spring Boot] 配置文件加载[超详细]

[Spring Boot] 配置文件加载[超详细]

作者头像
架构探险之道
发布2019-07-30 12:27:11
2.2K0
发布2019-07-30 12:27:11
举报
文章被收录于专栏:架构探险之道架构探险之道

[Spring Boot] 配置文件加载[超详细]

手机用户请 横屏获取最佳阅读体验, REFERENCES中是本文参考的链接,如需要链接和更多资源,可以关注其他博客发布地址。

平台

地址

CSDN

https://blog.csdn.net/sinat_28690417

简书

https://www.jianshu.com/u/3032cc862300

个人博客

https://yiyuery.club

分享整理 Spring Boot 下的配置文件加载

DEV-ENV

代码语言:javascript
复制
Spring Boot: 2.1.0
JDK: 1.8

主要分成以下几个方面来介绍下使用和配置方式:

  • 项目内配置文件加载方式
  • 项目外的配置文件
  • 复杂参数读取
  • yaml文件读取
  • Environment配置加载分析

常见配置加载方式

  • 项目内加载
  • 项目外加载
  • 复杂参数加载

项目内加载

1、 @Value 方式加载 application.yaml 中配置

application.yaml 中配置项

代码语言:javascript
复制
props:
  db-name: db_capsule

测试

代码语言:javascript
复制
@Value("${props.db-name}")
private String dbName;

@Test
public void testX1(){
    System.out.println(dbName);
}

2、 @PropertySource(value="classpath:props.properties")方式

props.properties 中配置项

代码语言:javascript
复制
a.b=1
代码语言:javascript
复制
@Configuration
@PropertySource("classpath:conf/props.properties")
public class PropertiesLoader {

    @Value("${a.b}")
    private Integer ab;

    @Bean
    public Integer ab(){
        return ab;
    }
}

测试

代码语言:javascript
复制
@RunWith(SpringRunner.class)
@SpringBootTest
public class CommonBootSupportApplicationTest {

    @Resource(name="ab")
    private Integer ab;

    @Test
    public void testX1(){
        System.out.println(ab);
    }
}

项目外加载

1、 配置 PropertyPlaceholderConfigurer

在项目外指定目录下新增一个properties文件

代码语言:javascript
复制
@Configuration
public class ResourceLoader {

    @Bean
    public PropertyPlaceholderConfigurer propertyPlaceholderConfigurer(){
        PropertyPlaceholderConfigurer configurer = new PropertyPlaceholderConfigurer();
        configurer.setLocation(new FileSystemResource(Paths.get("/Users/xiazhaoyang/Documents/capsule/architectrue-adventure/conf/props.properties")));
        //此处亦可添加项目路径下资源,使用ClassPathResource即可
        return configurer;
    }
}

测试

代码语言:javascript
复制
@RunWith(SpringRunner.class)
@SpringBootTest
public class CommonBootSupportApplicationTest {

    @Resource(name="ab")
    private Integer ab;
    @Value("${a.b.c}")
    private Integer abc;

    @Test
    public void testX1(){
        System.out.println(ab);
        System.out.println(abc);
    }
}

复杂参数加载

1、 实例对象成员属性自动注入

代码语言:javascript
复制
person:
  auto:
    name: x1
    age: 18
代码语言:javascript
复制
@Data
@ToString
@Component
@ConfigurationProperties(prefix = "person.auto")
public class PersonAutoConfig {

    private String name;

    private Integer age;
}

测试

代码语言:javascript
复制
@RunWith(SpringRunner.class)
@SpringBootTest
public class CommonBootSupportApplicationTest {

    @Resource
    private PersonAutoConfig personAutoConfig;

    @Test
    public void testX1(){
        //...
        System.out.println(personAutoConfig.toString());
        //...
    }
}

2、 实例集合属性自动注入

代码语言:javascript
复制
person:
  auto:
    name: x1
    age: 18
  list:
    personList:
      - name: x2
        age: 19
      - name: x3
        age: 20
代码语言:javascript
复制
@Data
@ToString
@Component
@ConfigurationProperties(prefix = "person.list")
public class PersonListAutoConfig {

    private List<PersonAutoConfig> personList;
}

测试

代码语言:javascript
复制
@Resource
private PersonListAutoConfig personListAutoConfig;

@Test
public void testX1(){
    System.out.println(personListAutoConfig);
}

自定义 YAML 文件读取

代码语言:javascript
复制
@Bean
@Primary
public CapPropertyPlaceholderConfigurer propertyConfigurer() throws IOException {
    CapPropertyPlaceholderConfigurer configurer = new CapPropertyPlaceholderConfigurer();
    YamlPropertiesFactoryBean yaml = new YamlPropertiesFactoryBean();
    //加载本地外部配置的yaml,也可以选择项目内
    yaml.setResources(new FileSystemResource(Paths.get(RunnerMonitor.getEnvConfPath().getConfPath(), "config.yaml").toFile()));
    Properties props = new Properties();
    props.putAll(Objects.requireNonNull(yaml.getObject()));
    //项目内 properties 配置文件加载
    props.load(PropertiesLoaderSupport.class.getResourceAsStream("/constants.properties"));
    configurer.setProperties(props);
    configurer.setFileEncoding(BasicConstants.DEFAULT_ENCODING);
    return configurer;
}

CapPropertyPlaceholderConfigurer

代码语言:javascript
复制
public class CapPropertyPlaceholderConfigurer extends PropertyPlaceholderConfigurer{

    private Properties capProps;

    @Override
    protected void processProperties(ConfigurableListableBeanFactory beanFactoryToProcess, Properties props) throws BeansException {
        capProps = props;
    }

    /**
     * 自定义配置获取,对外提供入口
     * @return
     */
    public Properties getCapProps() {
        return capProps;
    }
}

此处主要实现本地和外部配置文件加载的功能,并提供出口,在其他地方注入实例 CapPropertyPlaceholderConfigurer即可获取到对应自定义的配置属性信息

Environment配置加载分析

今天在做一个功能开发的时候,发现加载的配置,在 Environment实例中一直获取不到对应的配置属性,为此特地做个测试。

首先,外部 props文件展示下,方便比对

代码语言:javascript
复制
x.a.b=1
x.a.b.c=2

所以内外配置项各不相同,然后内部原有的配置变量 a.b=123删除掉,在外部 props中增加 a.b=321的配置,接下来我们 测试下输出

代码语言:javascript
复制
@Value("${a.b.c}")
private Integer abc;
@Value("${x.a.b.c}")
private Integer xabc;
@Value("${x.a.b}")
private Integer xab;
@Resource
private Environment environment;

@Test
public void testX1(){
    System.out.println(abc);
    System.out.println(xab);
    System.out.println(xabc);
    System.out.println(environment.getProperty("a.b"));
    System.out.println(environment.getProperty("x.a.b"));
    System.out.println(environment.getProperty("x.a.b.c"));
}

通过输出可以看出通过 PropertyPlaceholderConfigurer或其子类加载的配置,是不会写入到 Environment实例的。

此处需要 注意,由于配置了 PropertyPlaceholderConfigurer,需要注意在加载配置的时候,需要设置 ignore-unresolvable为true,不然会报 a.b无法通过${a,b}解析获取的错误

代码语言:javascript
复制
@Bean
public PropertyPlaceholderConfigurer propertyPlaceholderConfigurer(){
    PropertyPlaceholderConfigurer configurer = new PropertyPlaceholderConfigurer();
    configurer.setIgnoreUnresolvablePlaceholders(true);
    configurer.setLocation(new FileSystemResource(Paths.get("/Users/xiazhaoyang/Documents/capsule/architectrue-adventure/conf/props.properties")));
    return configurer;
}
代码语言:javascript
复制
2019-07-28 19:00:54.801  INFO 72049 --- [           main] e.c.b.s.CommonBootSupportApplicationTest : Started CommonBootSupportApplicationTest in 4.303 seconds (JVM running for 6.642)
321
1
2
null
null
null

那么,如果项目外定义的变量和项目内重复又会怎么样呢?我们在项目内 props配置文件中还原 a.b=123配置属性,测试下输出

代码语言:javascript
复制
321
1
2
123
null
null

显然, Environment 实例获取到的是项目内的配置项,和外部配置文件加载互不干扰。

所以该小节结论是外部通过 PropertyPlaceholderConfigurer注入的参数配置不会影响到 Environment获取的配置数据,如果想用自身配置项的话,需要自定义处理类,比如继承指定接口,或是通过配置项,将项目依赖的 Environment获取配置项的方式转换到自身配置类。

总结

好了,中心思想来了哦。总结下今天的整理,首先,我们了解了Spring Boot 中配置 文件的几种加载方式。然后呢?1、通过 @Value在注入类的实例中直接定义变量从 applicaition.yaml中获取 2、通过注解 @Configuration@PropertySource("classpath:conf/props.properties") 获取项目内其他路径的配置文件 3、怎么给注入的实例自动填充配置参数(集合和对象中的普通参数) 4、yaml配置文件的加载 5、外部配置文件的加载方式 6、外部配置文件加载和 Environment获取配置参数的方式是互不干扰的,如果需要改写某个类的实现,原来依赖于 Environment,但是需要调整为自定义的外部配置的话,需要自定义实现,比方说 jasypt的加密密钥,原生的方法使用的是项目内的配置文件,且是通过 Environment获取的。但是对于密钥这种敏感信息,我们一般是不放在项目代码中的,安全性需要保证,就需要自定义配置参数和加载路径。7、最后特别注意下如果配置了 PropertyPlaceholderConfigurer时最好是开启 configurer.setIgnoreUnresolvablePlaceholders(true);,不然遇到解析不到的属性就会报错。

REFRENCES

  • 解决 IllegalArgumentException: Could not resolve placeholder in string value "${XXXXXX}"
  • spring boot 自定义配置属性的各种方式
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-07-29,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 架构探险之道 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • [Spring Boot] 配置文件加载[超详细]
    • 常见配置加载方式
      • 项目内加载
    • 项目外加载
      • 复杂参数加载
    • 自定义 YAML 文件读取
      • Environment配置加载分析
        • 总结
          • REFRENCES
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档