【问题标题】:Getting a map property from environment variable with Spring使用 Spring 从环境变量中获取地图属性
【发布时间】:2020-01-31 15:44:44
【问题描述】:

我正在使用 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 覆盖键。即使我的地图是&lt;String,Object&gt;,值也会转换为字符串。

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

【问题讨论】:

    标签: java spring environment-variables


    【解决方案1】:

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

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

    【讨论】:

    • 我认为问题不在于顺序。应用程序正在环境变量中查找属性,并且仅在缺少任何属性时检查application.yaml。例如,如果我在application.yaml 中将键'a' 设置为值'yaml',并在环境变量中设置值env,则最终值将是env。问题是,即使在我的环境中找到了一些键,它仍然会求助于本地属性。即使在使用application-profile.yaml 之后,我仍然会重现同样的问题。
    • 如果您没有尝试加载配置文件,您必须声明它(例如,当您运行程序 -Dspring.profiles.active=profileName 时)。默认配置文件将始终被加载,因此它不像总是加载它们而不是诉诸本地属性。一个建议是 1. 首先删除文件并查看它加载的内容。 2. 加载不带默认值的配置文件,查看配置文件是否覆盖您的环境。 3.重新添加默认检查哪个更优。作为一种解决方法,您可以在 application-profile.yml 中使用环境变量(它们像 ${var_name} 一样使用)来注入
    • 我认为我们在这里混淆了一些东西!根据我发送的文档,环境加载了 9 和 10,而 yamls 紧随其后。这就是为什么你会得到变化。其次,地图不会重置,因为配置是附加的。所以他们只替换现有的密钥。这就是它不断添加的原因。 application.yml 应仅包含可在您的应用程序实例之间共享的最小配置。配置文件应该覆盖/填充细节。最后但并非最不重要的。 yaml加载时环境变量仍然存在,因此您可以使用map: ${mapValues} 添加它们。(如果json是supp)
    • 这是因为环境是基于键:值的。引入 yml 的地图(以及 xml 中的丑陋实现)。所以-在我看来-profiles是你解释的方式。
    • 这就是我提到“可配置”配置文件的原因。你有没有尝试一下,因为我真的很好奇地图是否可以这样配置。如果是,那么你有一个解决方案。您使用占位符配置文件部署所有内容,这些配置文件将填补环境中的空白!
    猜你喜欢
    • 1970-01-01
    • 2017-12-26
    • 1970-01-01
    • 2021-02-09
    • 2019-08-03
    • 2018-03-22
    • 2015-01-30
    • 2021-03-12
    • 1970-01-01
    相关资源
    最近更新 更多