【发布时间】:2014-09-23 02:01:45
【问题描述】:
我正在尝试为多个 Spring Boot 应用程序分区配置属性。我使用的是 Spring Boot 1.1.6,我们的配置属性以通常的 application.yml 样式在 YAML 中表示。我已经为常见的基本参数、常见的 DB 参数等创建了各种配置文件。我试图使用 Spring Boot 参考文档中提到的包含功能,但它似乎可以作为替代而不是包含。 IE。与我想要的完全相反。鉴于 application.yml 中的以下内容,我希望属性 name 在 bar 配置文件处于活动状态时具有值 bar,但是相反,它被设置为 foo (来自包含的配置文件)。我认为包含的概念意味着它首先被加载,并且在新配置文件中设置的任何同名属性都会覆盖包含的配置文件中的属性。有点像如果子类从超类中隐藏一个字段,则子类的任何实例都会反映被隐藏的值。这是文件:
spring:
profiles: foo
name: foo
--- # New YAML doc starts here
spring:
profiles:
include: foo
profiles: bar
name: bar
如果我在显式激活“bar”配置文件的测试用例中运行它,name 属性仍将是 foo:
SpringApplicationBuilder builder = new SpringApplicationBuilder(Application.class);
SpringApplication app = builder.application();
builder.profiles("bar");
ConfigurableApplicationContext ctxt = app.run();
String name = ctxt.getEnvironment().getProperty("name"); // Is always "foo" much to my surprise
但是,如果我注释掉包含:
spring:
profiles: bar
# profiles:
# include: foo
并在我的代码中明确激活这两个配置文件:
builder.profiles("foo", "bar");
然后它按我的预期工作,并且 name 属性设置为 bar。我宁愿处理 YAML 文件中的包含的主要原因是它对我的实际代码的影响较小,而且我可以在一个地方管理所有配置文件包含。使用另一种方法,如果我要重命名配置文件,我必须在整个项目中搜索配置文件字符串和可能的 @Profile 注释。那肯定更容易出错。我认为更灵活的解决方案是明确能够表达包含的配置文件是否覆盖子配置文件值。可能是这样的:
spring:
profiles: bar
profiles:
include: foo
override: false
也许我只是在这里遗漏了一些东西。有没有更好的方法来做到这一点?谢谢。
【问题讨论】:
-
spring.profiles.include的作用是影响Environment.getActiveProfiles()所以你应该如何测试结果。您似乎正在使用两个配置文件中都存在的属性键进行测试(要应用的最后一个获胜,它可能是“bar”,因为它在 YAML 中最后出现)。 -
感谢您的回复戴夫。这是我第一次听到这样解释。阅读 Spring Boot 参考文档,这当然不清楚(至少对我来说不是)。我认为这部分需要澄清,最好举个例子。谢谢。
-
捐款总是被感激地接受。不过,我还不清楚要澄清什么。
-
谢谢戴夫。我会尝试在我不那么丰富的业余时间里拼凑一些东西:-) 我想我的惊讶是我指定的包含实际上“隐藏”了指定包含的配置文件中的值。在我看来,我认为它有点像“子类”配置文件中的子类化和覆盖方法。我认为包含作为提供一些值的基类,并且包含它的“子类配置文件”将覆盖/隐藏“超类”配置文件提供的属性值。
-
我犯了同样的错误,至少这是我的测试显示的。您的 YAML 不正确;指定两个“spring:profiles:” YAML 节点会导致第二个节点覆盖第一个节点。您最后一个 sn-p 中的“栏”实际上被忽略了。如果有某种方法可以使 YAML 节点既是标量又是集合,我不知道,并且很高兴欢迎更正。 docs.spring.io/spring-boot/docs/current/reference/htmlsingle/… 中的注释是一种糟糕的说法,即“spring.profiles.include”在特定于配置文件的 YAML 文档中不起作用。
标签: spring spring-boot