我目前在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}
application-load-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-dev
和load-fixtures
添加新属性。
我理解配置文件特定属性优先于非配置文件特定属性。此外,非默认位置属性优先于默认位置的属性。但是在这里,两个配置文件(local-dev
和load-fixtures
)位于同一位置,并且它们也都是特定于配置文件的。
有什么方法可以解决这个问题?
提前致谢!
答案 0 :(得分:5)
我最近遇到了相同的问题,并且必须弄清楚Spring应用于多个配置文件特定属性文件的优先级。不幸的是,这没有很好的记录,我没有找到负责该代码的代码的位置。
然而,在经过一些测试和尝试之后,我非常确定它是这样的(或者至少以类似的方式):
可能某种地图用于收集所有不同地点和可能性的所有属性,您可以像记录here那样定义它们。例如,属性my.value
在application.properties
中定义,因此存储在提到的地图中。然后找到相同的属性作为Java系统属性。由于这种定义属性的方式在PropertySource
中更高 - 它将覆盖之前在地图中找到的值。在此之前,根据文档很清楚,Java系统属性将获胜。
但是,当我们在相同的优先级别上来两个不同的来源,比如两个不同的配置文件特定属性文件时,我认为文档不是100%明确的。但它在 24.4 :
中说如果指定了多个配置文件,则应用last-wins策略。例如,spring.profiles.active属性指定的配置文件将添加到通过SpringApplication API配置的配置文件之后,因此优先。
也许这只是一个在这里不是最优的例子,或者我只是不理解它。但我想这是"最后胜利"策略也适用于spring.profiles.active
中定义的所有配置文件。这意味着如果您运行java -jar -Dspring.profiles.active=dev,fix application.jar
,则application-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
。