【问题标题】:Issue with YAML-based configuration defaults in Spring Boot projectSpring Boot 项目中基于 YAML 的配置默认值的问题
【发布时间】:2017-01-03 22:03:56
【问题描述】:

我有一个 YAML 配置文件如下:

spring.profiles: master
cars:
  - 
    color: red
    style: sedan
    doors: 4
  -
    color: blue
    doors: 4
  - 
    color: black
---
spring.profiles: default
cars-default:
  color: not specified
  style: not specified
  doors: not specified

如您所见,cars 是一个列表,但 cars-default 不是。我知道,如果您定义默认配置文件以使“扁平化”布局与您的活动配置文件相匹配,Spring 将愉快地合并两个配置文件,以便活动配置文件中定义的属性将覆盖默认值。

我的挑战是我想要一个单一组默认值来覆盖每个 List 对象,所以结果属性最终是这样的:

cars:
  - 
    color: red
    style: sedan
    doors: 4
  -
    color: blue
    style: not specified   
    doors: 4
  - 
    color: black
    style: not specified   
    doors: not specified

为了让事情稍微复杂一点,这些属性映射到的 Car POJO 具有自己的硬编码默认值,我无法覆盖,因此只需填充 Car 对象和 DefaultCar 对象并对其应用合并操作这两个都行不通。

基本上,我需要发生的是两组属性在在 Car 对象中实例化和设置值之前合并。

我希望有一种方法可以利用 Spring 的属性解析器,以便我可以覆盖默认行为,尽管我对 Spring 的这方面不够熟悉,所以我真的不知道在哪里开始。

【问题讨论】:

  • 您的陈述“如您所见,汽车是一个列表,但汽车默认不是”是错误的,即使您将其重写为“如您所见,的值 cars 是一个序列,但 cars-default 的值不是"。两个值都是序列。 cars 是作为字符串加载的标量,cars-default 也是如此。它们都是 YAML 配置文件中 two 文档中每个顶级映射的键。 YAML 没有称为List 的概念。 List 是在 Java 程序中加载 YAML 文件时表示的序列。您的第二个“文件”是无效的 YAML
  • 抱歉,很晚,YAML 输入错误。它已被修复。顺便说一句 - 如果我将 cars-default 更改为一个序列并将密钥更改为“cars:”,Spring 会将默认值与活动(主)配置文件中的第一个序列合并,而不是其余的。这就是我试图通过 Spring 以编程方式实现的目标,如果可能的话。

标签: spring properties spring-boot configuration yaml


【解决方案1】:

如果您的 YAML 解析器支持,您可能只能使用标准 YAML 锚点和别名以及 the merge key 工具。这个:

spring.profiles: master
_: &car-default
  color: not specified
  style: not specified
  doors: not specified
cars:
  - <<: *car-default
    color: red
    style: sedan
    doors: 4
  - <<: *car-default
    color: blue
    doors: 4
  - <<: *car-default
    color: black

加载到兼容的解析器中,就像您使用过的一样:

spring.profiles: master
_:
  color: not specified
  style: not specified
  doors: not specified
cars:
- color: red
  style: sedan
  doors: 4
- color: blue
  style: not specified
  doors: 4
- color: black
  style: not specified
  doors: not specified

确保锚点 (&amp;car-default) 在同一个 YAML 文档中定义(您有两个)并且在使用它之前(使用 *car-default)。它不必定义为(顶级或其他)键的值,映射可以是序列中的元素,例如序列的第一个元素是cars 的值:

spring.profiles: master
cars:
  - &car-default
    color: not specified
    style: not specified
    doors: not specified
  - <<: *car-default
    color: red
    style: sedan
    doors: 4
  - <<: *car-default
    color: blue
    doors: 4
  - <<: *car-default
    color: black

当然,Spring 必须忽略锚值中的默认值,因此您可能需要找到一些“注释”键值对并将其存储在值部分中。

【讨论】:

  • 酷。谢谢!我会在星期一试试。希望我的 YAML 解析器能够合作。 :)
  • 我尝试了所有 3 条建议,但都没有奏效。似乎 Spring 的 ConfigurationProperties 处理器忽略了锚点。它所做的是将 yaml 展平,使其与 .properties 文件的格式匹配,然后尝试将默认配置文件(如果存在)与任何标记为活动的配置文件合并。不幸的是,它似乎希望在属性名称方面进行一对一匹配以进行合并。 ://
  • @bitstream 很抱歉听到这个消息,很遗憾我现在没有其他建议。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-12-27
  • 2020-01-23
  • 2020-05-31
  • 2021-11-23
  • 1970-01-01
  • 1970-01-01
  • 2020-12-12
相关资源
最近更新 更多