【问题标题】:Spring "spring.profiles.include" overridesSpring“spring.profiles.include”覆盖
【发布时间】:2018-05-02 06:14:06
【问题描述】:

我的意图是在 Spring Boot 应用程序中有两个配置文件 - 开发和生产一个。开发配置文件只是为了覆盖生产配置文件的一些变量(例如内存数据库而不是云中的数据库)。由于我预计将来会对生产配置文件进行一些更改,因此在开发配置文件中复制变量似乎不是一个解决方案。

所以,在Spring Reference 中,我读到spring.profiles.include 应该只从引用的配置文件中添加属性。

有时,将特定于配置文件的属性添加到活动配置文件而不是替换它们是很有用的。 spring.profiles.include 属性可用于无条件添加活动配置文件。

但是,根据我的检查,它会覆盖它。因此,当有两个配置文件 foo 和 bar 时,在单独的 yaml 文件中:

应用程序-foo.yaml:

myproperty: 44

application-bar.yaml:

spring:
  profiles:
    include: foo
    active: bar,foo
myproperty: 55

在IDE中设置-Dspring.profiles.active=bar变量,myproperty的运行时值为44。这意味着barfoo覆盖,它应该只添加属性,而不是覆盖它们。启动应用程序时,我得到:

以下配置文件处于活动状态:foo,bar

我在另一个问题中按照answer 的建议将spring.profiles.active=bar 添加到application-bar.yaml,但它没有效果 - 属性是否存在没有区别(我也尝试使用破折号列表而不是逗号分隔值)。

我的问题是,它应该如何工作(那么 Spring Reference 具有误导性)?如果是这样,有什么解决办法吗?

在 github 上的应用程序源代码中添加 link

【问题讨论】:

    标签: spring spring-boot spring-profiles


    【解决方案1】:

    根据 Spring Boot 文档herespring.profiles.include 用于添加来自其他配置文件的属性。如果该属性不存在于活动配置文件中,它将从其他配置文件添加该属性。但如果它存在,那么它将覆盖并且最后应用的获胜

    有时,将特定于配置文件的属性添加到活动配置文件而不是替换它们是很有用的。 spring.profiles.include 属性可用于无条件添加活动配置文件。

    【讨论】:

    • 我知道链接 - 它提到“spring.profiles.include 属性可用于无条件地添加活动配置文件。” - 这个描述对我来说是模棱两可的。但这很好,有什么办法可以只从其他配置文件导入设置,而不是让它们覆盖当前配置文件?
    【解决方案2】:

    我们以稍微不同的方式实现 Spring 活动配置文件。假设默认属性文件 application.yml 包含在生产环境和开发环境中相同的所有默认值。

    分别为名为 application-prd.ymlapplication-dev.yml 的生产和开发文件创建单独的属性。这些文件可能包含额外的属性或覆盖一些默认属性。

    在应用程序启动期间,我们将spring.profiles.active 作为环境变量传递。例如,

    -Dspring.profiles.active=prd

    将接收application-prd.ymlapplication.yml

    -Dspring.profiles.active=dev

    将接收application-dev.ymlapplication.yml

    【讨论】:

    • 谢谢,我认为它足以满足我的目的。它仍然不能让开发人员能够覆盖自定义属性文件,所以这让我创建了额外的文件(最终有 application.yaml、application-foo.yaml 和 application-bar.yaml),但只要我能够满足要求就可以了。
    【解决方案3】:

    您可以在application-bar.yaml 中添加新的个人资料:

    spring.profiles.include: foo,foo-override
    myproperty: 33
    
    ---
    spring.profiles: foo-override
    myproperty: 55
    

    顺序是:33 in bar44 in foo 覆盖,被55 in foo-override 覆盖。

    【讨论】:

      【解决方案4】:

      给定:

      • 文件:application-default.yml, application-foo.yml, application-bar.yml
      • myproperty: default 在 application-default.yml 中
      • myproperty: foo 在 application-foo.yml
      • myproperty: bar 在 application-bar.yml

      我认为这两个使用配置文件的用例在含义上有点相反:

      1. 在最常见的情况下(-Dspring.profiles.active 但没有spring.profiles.include):

        1. 当配置文件 foo 或 boo 被激活时,属性来自 application-foo.yml(或 application-bar.yml)将添加/覆盖 来自 application-default.yml 的。
        2. 激活配置文件 foo,bar 后,来自 bar 的属性将添加/覆盖那些来自 application-foo.yml 的属性,然后是来自 application-default.yml 的那些。

        例如:-Dspring.profiles.active=foo,bar application-bar.yml 中的属性获胜(覆盖)-> myproperty: bar

      2. 第二种情况(使用spring.profiles.include

        1. include 语句中的属性添加/覆盖使用spring.profiles.include 的 application-*.yml 文件中的属性

        即:如果 application-boo.yml 包含 spring.profiles.include=foo 则来自 application-foo.bar adds/override properties from from application-bar.yml 的属性添加/覆盖来自 application-default.yml 的那些。

        另一方面(我想)如果 application-boo.yml 包含spring.profiles.include=default,foo,那么来自application-foo.yml 的属性将添加/覆盖来自application-default.yml 的属性,这些属性将添加/覆盖来自application-bar.yml 的属性。所以myproperty: bar。我不建议将defaultspring.profiles.include 结合使用,因为这样会混合两种情况,并且考虑到application-default.yml 在springboot 中有特殊处理,覆盖策略是违反直觉的。

      我也承认我根本不喜欢在 application-*.yml 文件中使用 spring.profiles.active。我更喜欢使用系统属性(包括 Maven)或环境变量来激活配置文件。 IMO 它让我更清楚地了解整个配置文件。

      如果我(以上)推理我走错了路,请告诉我。

      【讨论】:

        【解决方案5】:

        Spring Boot 2.4 更改了包含多个配置文件的机制,以使用新的profile groups 功能,而不是在特定于配置文件的文档中使用spring.profiles.include。这意味着您的配置对新版本的 Spring Boot 不再有效,需要进行更改。

        也就是说,您的用例似乎不太适合配置文件组,因为它并没有真正组合两个配置文件,而是覆盖默认值。因此,我建议使用 in another answer 建议的方法,将公共和默认属性放在共享的 application.yaml 文件中,并且只在配置文件特定的文档中包含特定于环境的值和覆盖。

        application.yaml

        spring:
          myproperty: 44 # Default value
        

        application-bar.yaml

        spring:
          myproperty: 55 # Override default
        

        请注意,Spring Boot 支持 multi-document files,因此如果需要,可以将它们组合成一个 application.yaml 文件:

        spring:
          myproperty: 44 # Default value
        ---
        spring.config.activate.on-profile=bar # These configs apply to the bar profile
        spring:
          myproperty: 55 # Override default
        

        相关 2.4 更改

        从 Spring Boot 2.4 开始,不再可以在特定于配置文件的文档中使用 spring.profiles.include,除非使用 spring.config.use-legacy-processing=true 启用了 legacy mode。根据 2.4 Spring Boot Config Data Migration Guide:

        您仍然可以使用 spring.profiles.include 属性,但只能在非特定于配置文件的文档中使用。

        这种方法已被profile groups 功能所取代。根据migration guide

        如上所述,不能再在特定于个人资料的文档中使用 spring.profiles.include,因此该文件无效。

        由于这个用例很常见,我们尝试提供另一种方式来支持它。在 Spring Boot 2.4 中,您可以使用 “profile groups” 功能。

        此功能记录在 Spring Boot 参考指南的 Profile Groups 部分:

        配置文件组允许您为相关的配置文件组定义逻辑名称。

        例如,我们可以创建一个由proddbprodmq 配置文件组成的production 组。

        spring:
          profiles:
            group:
              production:
              - "proddb"
              - "prodmq"
        

        现在可以使用--spring.profiles.active=production 启动我们的应用程序,一键激活productionproddbprodmq 配置文件。

        迁移指南points out 指出spring.profile.group 属性不能在特定于配置文件的文档中使用。

        spring.profile.group 属性不能用于特定于配置文件的文档中。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2014-10-26
          • 1970-01-01
          • 2019-10-03
          • 2013-03-12
          • 2010-11-15
          • 2015-05-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多