SpringBoot中使用configtree读取树形文件目录中的配置详解

 更新时间:2023年12月31日 08:46:55   作者:理想万岁万万岁  
这篇文章主要介绍了SpringBoot中使用configtree读取树形文件目录中的配置详解,configtree通过spring.config.import + configtree:前缀的方式,加载以文件名为key、文件内容为value的配置属性,需要的朋友可以参考下

一、介绍

相信绝大多数使用springboot开发项目的朋友们在添加配置时,通常都是通过以下几种方式:

  • 在classpath下添加application.yml或application.properties配置文件,或通过spring.config.location指定配置文件位置。
  • 通过spring.config.additional-location指定额外的配置文件位置。
  • 通过spring.config.import导入指定位置的配置文件。

但无论通过哪种方式,其配置的形式都是通过在配置文件中通过key - value的形式添加具体配置的,且配置文件类型为yaml或properties。如下所示:

properties文件内容示例

key1 = value1

yaml文件内容示例

key1: value1

其中key1作为配置名,value1作为配置值。

今天给大家介绍另一种配置形式,该配置使用文件名作为配置名,文件内容作为配置值。

如文件名为username的内容如下:

admin

文件名为password的内容如下:

123456

二、演示环境

本演示项目的环境如下:

  • java:1.8
  • springboot:2.4.3

三、项目演示

本项目演示的是,在指定目录中添加配置文件,并以文件名为key,文件内容为value;然后在application.yml配置文件中通过spring.config.import指定configtree将目录中的所有配置文件添加到项目的环境中,并通过placeholder${}的形式获取配置。

1. 配置文件

我们在本地文件系统中添加配置文件,其目录结构如下所示

  /
    etc/
      app/
        config/
          admin/
            username
            password
          db/
            username
            password
          nacos/
            username
            password

各个配置文件内容如下所示

/etc/app/config/admin/username

admin

/etc/app/config/admin/password

123456

/etc/app/config/db/username

mysql

/etc/app/config/db/password

123456

/etc/app/config/nacos/username

nacos

/etc/app/config/nacos/password

nacos

2. 导入配置

在application.yml配置文件中添加配置spring.config.import。

注意,当我们要添加以文件名为key,文件内容为value的配置文件时,必须在路径前添加前缀configtree:,且路径最后以/结尾。

另外,该路径支持*通配符。

spring:
  config:
    import:
      - configtree:/etc/app/config/

如上所示,springboot将读取路径/etc/app/config/(包括子目录)中的所有文件,并以文件名为key,文件内容为value。

3. 检测配置属性

当我们按照上面示例配置时,由于在application.yml中配置的spring.config.import目录为/etc/app/config/,因此我们可以通过admin.username、admin.password、db.username、db.password、nacos.username和nacos.password获取对应文件内容的值。

下面我们启动项目对其进行检验。

启动项目:

在这里插入图片描述

输出:

在这里插入图片描述

四、应用场景

看到这里,想必很多小伙伴虽然知道springboot如何通过spring.config.import + configtree来读取以文件名为key,文件内容为value的配置,但是这种配置方式使用起来并不方便,且一个文件仅对应一个配置属性,那如果需要大量配置岂不是要创建大量文件?

其实,使用该配置方式和使用application.yml方式应该是相辅相成的,两者应当配合使用。

当我们在云平台(比如docker)上运行应用程序时,有时需要读取容器提供的配置值。而我们多数情况下都是通过该容器的环境变量来获取所需的配置,但是如果我们可能会频繁修改该环境变量或该变量需要加密时,就可能暴露出它的缺点了。因为容器的环境变量是在创建镜像的时候就确定的,当我们需要修改该环境变量时就意味着已经创建的容器需要删除了。

所以我们可以通过容器挂载卷的方式,将该环境变量保存在文件中,通过挂载卷将配置文件挂载到容器中。

五、源码解析

springboot通过ConfigTreeConfigDataLocationResolver和StandardConfigDataLocationResolver两种配置文件位置解析器来解析配置文件的位置,然后通过ConfigTreeConfigDataLoader和StandardConfigDataLoader来加载对应配置文件中的配置内容。

因此结合本文重点,我们应主要关注ConfigTreeConfigDataLocationResolver和ConfigTreeConfigDataLoader是如何解析配置文件的位置并从文件中读取配置内容的。

1. ConfigTreeConfigDataLocationResolver

首先我们查看ConfigTreeConfigDataLocationResolver是如何解析出配置文件目录的,主要分两步:①判断配置的路径是否满足解析的条件,②解析配置文件的位置。

判断配置的路径是否满足解析的条件

该判断逻辑通过isResolvable()方法完成,主要判断依据就是配置的spring.config.import值是否包含configtree:前缀,如果包含,则满足条件。

private static final String PREFIX = "configtree:";
@Override
public boolean isResolvable(ConfigDataLocationResolverContext context, ConfigDataLocation location) {
    return location.hasPrefix(PREFIX);
}

解析配置文件的位置

该逻辑通过方法resolve()完成,其目的是根据配置的spring.config.import目录转换为该目录下文件的资源。

@Override
public List<ConfigTreeConfigDataResource> resolve(ConfigDataLocationResolverContext context,
                                                  ConfigDataLocation location) {
    try {
        return resolve(context, location.getNonPrefixedValue(PREFIX));
    }
    catch (IOException ex) {
        throw new ConfigDataLocationNotFoundException(location, ex);
    }
}
private List<ConfigTreeConfigDataResource> resolve(ConfigDataLocationResolverContext context, String location)
    throws IOException {
    // 目录必须以“/结尾”
    Assert.isTrue(location.endsWith("/"),
                  () -> String.format("Config tree location '%s' must end with '/'", location));
    // 如果目录不是通配符的形式,则直接根据该目录获取该目录下文件的资源集合。
    if (!this.resourceLoader.isPattern(location)) {
        return Collections.singletonList(new ConfigTreeConfigDataResource(location));
    }
    // 如果目录是通配符的形式,则对其进一步处理,获取该目录下文件的资源集合。
    Resource[] resources = this.resourceLoader.getResources(location, ResourceType.DIRECTORY);
    List<ConfigTreeConfigDataResource> resolved = new ArrayList<>(resources.length);
    for (Resource resource : resources) {
        resolved.add(new ConfigTreeConfigDataResource(resource.getFile().toPath()));
    }
    return resolved;
}

2. ConfigTreeConfigDataLoader

然后我们分析ConfigTreeConfigDataLoader是如何根据配置文件资源加载其内容的。

在这里插入图片描述

在加载配置属性中,我们看到该方法主要分两步

①根据文件资源获取文件路径path

②根据文件路径获取该文件中的配置。我们在方法结束时添加断点,然后启动项目,让代码运行到断点处。如下图所示,我们发现springboot已经按照预期将各个配置文件读取成功了。

在这里插入图片描述

任意点击其中一个元素,可以看到配置文件中的内容也已经被加载了

在这里插入图片描述

最后将其封装到ConfigData对象中返回。

六、总结

  • 通过spring.config.import + configtree:前缀的方式,加载以文件名为key、文件内容为value的配置属性。
  • configtree:应以/结尾。
  • 适用于代替在云平台中读取加密的系统环境变量的场景。

到此这篇关于SpringBoot中使用configtree读取树形文件目录中的配置详解的文章就介绍到这了,更多相关SpringBoot读取文件目录配置内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • java JSON解析库Alibaba Fastjson用法详解

    java JSON解析库Alibaba Fastjson用法详解

    这篇文章主要介绍了java JSON解析库Alibaba Fastjson用法,结合实例形式详细分析了java JSON解析库Alibaba Fastjson的基本功能、原理、用法及操作注意事项,需要的朋友可以参考下
    2020-04-04
  • Java和C++通过new创建的对象有何区别?

    Java和C++通过new创建的对象有何区别?

    Java和C++都是面向对象的编程语言,然而Java和C++在创建对象时却存在不同的方式,由于方式的不同导致在内存中管理的不同。这篇文章主要给大家介绍了关于Java和C++通过new创建对象区别的相关资料,需要的朋友可以参考借鉴,下面来一起看看吧。
    2017-11-11
  • Java跳出多重嵌套循环过程解析

    Java跳出多重嵌套循环过程解析

    这篇文章主要介绍了Java跳出多重嵌套循环过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-12-12
  • SpringMVC @RequestBody自动转json Http415错误的解决

    SpringMVC @RequestBody自动转json Http415错误的解决

    这篇文章主要介绍了SpringMVC @RequestBody自动转json Http415错误的解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-04-04
  • java导出大批量(百万以上)数据的excel文件

    java导出大批量(百万以上)数据的excel文件

    这篇文章主要为大家详细 介绍了java导出大批量即百万以上数据的excel文件,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-04-04
  • Java配置win10环境变量过程图解

    Java配置win10环境变量过程图解

    这篇文章主要介绍了Java配置win10环境变量过程图解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-05-05
  • IDEA中java断言assert语法及使用

    IDEA中java断言assert语法及使用

    这篇文章主要介绍了IDEA中java断言assert语法详解,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-04-04
  • MyBatis-Plus通过version机制实现乐观锁的思路

    MyBatis-Plus通过version机制实现乐观锁的思路

    version机制的核心思想就是,假设发生并发冲突的几率很低,只有当更新数据的时候采取检查是否有冲突,而判断是否有冲突的依据就是version的值是否被改变了,这篇文章主要介绍了MyBatis-Plus通过version机制实现乐观锁的思路,需要的朋友可以参考下
    2021-09-09
  • java文件和目录的增删复制

    java文件和目录的增删复制

    这篇文章主要为大家详细介绍了java文件和目录的增删复制,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-06-06
  • 必须详细与全面的Java开发环境搭建图文教程

    必须详细与全面的Java开发环境搭建图文教程

    本篇文章内容包括:Linux理论与实操,MySQL实操,JDK实操,Tomcat实操和Tomcat实操,需要的朋友可以参考下
    2019-11-11

最新评论