我有一个看起来像这样的 application.yml:
root:
mapkey:
name-with-dashes:
vara: some value 1
varb: 1
different-name-with-dashes:
vara: some value 2
varb: 2
我正在使用 @ConfigurationProperties
注释来注入(inject)与此结构匹配的配置 POJO。它看起来基本上是这样的(为了可读性删除了构造函数等,但只知道它有效):
@Configuration
@ConfigurationProperties("root")
public class ParentConfig {
private Map<String, ChildConfig> mapkey;
}
public class ChildConfig {
private String vara;
private Integer varb;
}
在本地测试时,我没有任何问题,注入(inject)工作正常。
但是,我在尝试使用系统变量部署和覆盖这些字段时遇到了问题。来自Springboot Documentation ,它表示应通过将句点转换为下划线、删除破折号并转换为大写来创建系统属性。在我的例子中,我最终得到这样的变量:
ROOT_MAPKEY_NAMEWITHDASHES_VARA: deployment value 1
ROOT_MAPKEY_NAMEWITHDASHES_VARB: 6
ROOT_MAPKEY_DIFFERENTNAMEWITHDASHES_VARA: deployment value 2
ROOT_MAPKEY_DIFFERENTNAMEWITHDASHES_VARB: 12
但是,当我使用这些变量运行应用程序并检查 ParentConfig
对象时, map 如下所示:
{
mapkey: {
name-with-dashes: {
vara: deployment value 1
varb: 6
},
namewithdashes: {
vara: deployment value 1
varb: 6
},
different-name-with-dashes: {
vara: deployment value 2
varb: 12
},
differentnamewithdashes: {
vara: deployment value 2
varb: 12
}
}
}
它正在复制带和不带破折号的属性,我不知道为什么。不仅如此,所有的值都有部署值,而不是 application.yml 值。非常困惑。
最佳答案
最近,我遇到了一个与“relaxed binding”类似的问题。我的问题是我的内部配置没有被外部配置覆盖,其中内部配置完全匹配而外部配置不是。所以这里有相似之处,但不完全与你的相似。但是,当我将外部配置更改为完全匹配时,它会覆盖。
我还没有找到关于此的任何文档,但我相当确定这是一个优先问题以及绑定(bind)实际上是多么“宽松”。就我而言,完全有道理的是,内部精确匹配优先,“宽松的”外部匹配(旧错字)被丢弃。
回答你的问题,因为你的对象是一个 map ,其中的对不以严格的键开头。这使得覆盖更加模糊(如果不是不可能的话)。我的想法是,除非完全匹配,否则它无法区分新 key 和要覆盖的 key 。因此,将新系统环境变量作为新 key 插入是有意义的。
现在您可能会问,在这种情况下如何使其精确。嗯,你不能,除非你改变你的内部配置以遵循系统属性命名规则。或者您可以拥有具有准确命名的外部配置文件。
总的来说,我认为“松散绑定(bind)”更像是一个后备选项。它不应该是你的第一选择。 尽可能尝试使用精确命名。我想说的是,当旧项目升级到新版本并且开发人员不必通过大量配置文件来更新时,此功能可能更有用更改名称。
关于java - Spring Boot 与 map 的宽松绑定(bind)是重复属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62270318/