【问题标题】:How to override profile-specific properties with a different profile?如何使用不同的配置文件覆盖配置文件特定的属性?
【发布时间】:2017-11-16 12:42:32
【问题描述】:

我目前在 Spring Boot 中有以下配置设置:

application.properties

app.database.host=${DB_HOST}
app.database.port=${DB_PORT}
app.database.name=${DB_NAME}
app.database.user=${DB_USER}
app.database.password=${DB_PASSWORD}
app.database.schema=${DB_SCHEMA:public}
spring.datasource.url=jdbc:postgresql://${app.database.host}:${app.database.port}/${app.database.name}
spring.datasource.username=${app.database.user}
spring.datasource.password=${app.database.password}
spring.datasource.driver-class-name=org.postgresql.Driver
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect

application-local-dev.properties:

app.database.host=${DB_HOST:localhost}
app.database.port=${DB_PORT:5432}
app.database.name=${DB_NAME:db_name}
app.database.user=${DB_USER:root}
app.database.password=${DB_PASSWORD:root}
app.database.schema=${DB_SCHEMA:public}

应用加载-fixtures.properties:

spring.profiles.include=local-dev
spring.profiles.active=load-fixtures,local-dev
app.database.name=${DB_NAME:db_name}_fixtures

这里的想法是,在默认模式下启动应用程序时,如果缺少数据库名称等关键属性,它将无法启动。 它们应该通过环境变量传递。

出于开发目的,在设置项目时这是不必要的开销,因为我们有一个带有静态凭据的 docker 容器,我想将它们作为默认值提供。因此,我创建了一个配置文件local-dev,它将使用默认值来连接到我们的 docker 数据库,并且仍然能够通过环境变量覆盖它们,以防有人需要。 到这里为止,一切正常。

但是现在,我们还有一个配置文件,用于将夹具加载到数据库中(删除所有表,重新创建并用数据填充它们)。 出于显而易见的原因,我想确保这不能在任意数据库上完成,所以我创建了一个配置文件 load-fixtures,它应该继承 local-dev 的所有属性并覆盖数据库名称。但是,这种方法似乎是错误的。我可以在 spring 日志中看到配置文件已正确加载:

2017-11-16 13:32:11.508  INFO 23943 --- [           main] Main:
The following profiles are active: load-fixtures,local-dev

但它仍然使用local-dev 配置文件提供的数据库名称。

当我删除线时

app.database.name=${DB_NAME:db_name}

来自local-dev 配置文件,它可以工作。

但是,我要避免的是,每当我们向项目添加新的配置属性时,都必须向 local-devload-fixtures 添加新属性。

我了解配置文件特定属性优先于非配置文件特定属性。而且,非默认位置属性优先于默认位置的属性。但是在这里,两个配置文件(local-devload-fixtures)都在同一个位置,而且它们也是特定于配置文件的。

解决这个问题的正确方法是什么?

提前致谢!

【问题讨论】:

    标签: spring-boot


    【解决方案1】:

    我最近遇到了完全相同的问题,并且必须弄清楚 Spring 将哪个优先级应用于几个配置文件特定的属性文件。不幸的是,这没有很好的记录,我没有找到负责该代码的位置。

    但是经过一些测试和尝试后,我很确定它是这样工作的(或至少以类似的方式): 可能某种地图用于收集所有不同地点和可能性的所有属性,您可以在其中定义它们,如记录的here。例如,属性my.value 定义在application.properties 中,因此存储在上述映射中。然后找到与 Java 系统属性相同的属性。由于这种定义属性的方式在PropertySource-order 中更高,它将覆盖之前在地图中找到的值。直到这里,根据文档,Java 系统属性将获胜。

    但是,当我们在同一优先级上找到两个不同的来源时,例如两个不同的配置文件特定属性文件,我认为文档并不是 100% 清楚的。但是它在 24.4 中说:

    如果指定了多个配置文件,则应用最后获胜的策略。例如,由 spring.profiles.active 属性指定的配置文件添加在通过 SpringApplication API 配置的配置文件之后,因此具有优先权。

    也许这只是这里不是最佳的示例,或者我只是没有正确理解它。但我想“最后获胜”策略也适用于所有配置文件,例如在spring.profiles.active 中定义的配置文件。这意味着如果你运行java -jar -Dspring.profiles.active=dev,fix application.jarapplication-fix.properties 中的属性将覆盖application-dev.properties 中具有相同键的属性的值。

    所以在你的情况下,考虑到你的应用程序的输出,我猜你指定了类似java -jar -Dspring.profiles.active=load-fixtures,local-dev application.jar 的东西。如果我是正确的,您只需将其更改为 java -jar -Dspring.profiles.active=local-dev,load-fixtures application.jar

    【讨论】:

      猜你喜欢
      • 2012-03-07
      • 2021-09-14
      • 2013-02-22
      • 1970-01-01
      • 2018-11-29
      • 1970-01-01
      • 2016-07-12
      • 2021-06-22
      • 1970-01-01
      相关资源
      最近更新 更多