首页 > 解决方案 > 使用 Spring 从环境变量中获取地图属性

问题描述

我正在使用 Spring Boot 创建一个微服务,该微服务使用一些使用@Value和加载的属性@ConfigurationProperties。这些属性将在中定义默认值,application.yaml但我想用环境变量覆盖它们。我已经设法使用几乎所有基本属性类型来做到这一点,但我无法使用地图。

这是检索属性的代码,因此地图位于configuration.map

@Data
@ConfigurationProperties(prefix = "configuration")
public class MapConfig{
    private Map<String, Object> map;
}

我在其中的默认值application.yaml是:

configuration:
  map:
    a: "A"
    b: 2
    c: true

这工作正常,我得到一个包含这些键值条目的映射。当我尝试使用环境变量初始化地图时,问题就来了。我尝试了多种变体,CONFIGURATION_MAP='{aa:"aa", bb:12, cc:true}'每次启动应用程序时,我都会得到定义的默认值,application.yaml但没有环境映射的痕迹。

我还尝试添加变量,例如CONFIGURATION_MAP_AA='HELLO',我能够在我的地图中放置新值。但是我所能做的就是添加信息,但我在 yaml 中编写的默认值仍然存在。在这种情况下,我得到:

{
    "aa": "HELLO",
    "a": "A",
    "b": 2,
    "c": true
}

这不是我正在寻找的行为。我想完全覆盖默认地图而不是添加新信息。它还有一个问题,就是以这种方式添加的键总是转换为小写,所以我不能用 camelCase 覆盖键。即使我的地图是<String,Object>.

谁能告诉我如何使用环境变量正确初始化地图或为我指明正确的方向?非常感谢!

标签: javaspringenvironment-variables

解决方案


问题是加载属性的顺序。看看这个解释加载顺序的文档。我不知道它是否对您的场景有用,但您可以尝试创建一个配置文件(例如application-other.yml)并加载它。之后会加载application.yml

演员阵容来自您列表中最常见的类型。最后,所有三个“ name, 1, true”都可以是字符串。我想不出一种加载方式,Object但是您可以根据自己的喜好重新转换您的字符串(如果需要的话。)否则将其分解为多个特定于类型的映射(Map<String,String> , Map<String,Boolean>, Map<String,Integer>


推荐阅读