在使用 PropertiesLauncher 启动的 Spring-boot(特定于配置文件)应用程序中覆盖应用程序属性时出现问题

2022-09-03 07:42:26

我尝试使用文件系统上的覆盖文件中声明的另一个值来重写类路径上特定于配置文件的应用程序属性文件中声明的属性时遇到困难。

我有一个自动配置的Spring-boot应用程序(即使用),它具有多个配置文件,我使用它们而不是(原因与部署约束有关 - 我需要将松散目录而不是归档文件部署到只读文件系统中。@EnableAutoconfigurationPropertiesLauncherJarLauncher

在我的应用程序的根目录中,我有一些特定于配置文件的应用程序属性,例如:

application-dev.properties
application-qa.properties
application-prd.properties

比方说,为了包含以下内容的论证:application-dev.properties

foo.bar=baz
foo.baz=other

对于任何环境,都可能需要重写现有属性,并提供一个缺少的属性(例如生产密码),我看到的问题是重写已在类路径上的文件中声明的属性。(提供类路径文件中不存在的属性工作正常,这不是问题所在。application-${profile}.properties

假设我在文件系统位置有一个覆盖属性文件,例如:

/local/appname/dev/overrides/application.properties

并且我想覆盖属性,以及声明一个新属性。foo.barfoo.password

因此,覆盖文件的内容是:

foo.bar=overridden-value
foo.password=something

当我启动应用程序时,我使用命令行,如下所示:

java -Dspring.config.location=file:/local/appname/dev/overrides/ 
     -Dspring.profiles.active=dev 
     org.springframework.boot.loader.PropertiesLauncher 
     --debug &

我看到的问题是,尽管,文件中未声明的属性被拾取,但覆盖被忽略 - 我仍然看到值,而不是值,从。foo.passwordapplication-dev.propertiesfoo.barbazapplication-dev.propertiesoverridden-value/local/appname/dev/overrides/application.properties

启用该选项后,我可以看到日志记录,它已按该顺序加载了覆盖文件(来自文件系统)和特定于配置文件的文件(来自类路径)。--debugConfigFileApplicationListener

我倾向于得出一个可能幼稚的结论,即由于覆盖文件首先列出,因此它首先被加载,然后被类路径中的“默认”配置文件特定文件覆盖,该文件稍后列出。但是,我很欣赏日志中的列表顺序并不一定与行为相关。我已经尝试过改变在属性上声明的路径的顺序,因此之前已列出,但这没有帮助,我也不相信它会这样做,因为Spring-boot文档明确指出,即使您为 提供了值,也始终会搜索默认属性位置。spring.config.locationclasspath:file:...spring.config.location

Spring-boot 文档非常具体地说明了为 Spring-boot 可执行 JAR 解析属性的顺序,按优先级降序排列:

  1. 命令行参数。
  2. Java 系统属性 ()。System.getProperties()
  3. 操作系统环境变量。
  4. 来自 的 JNDI 属性java:comp/env
  5. 仅在 中具有属性的 A。RandomValuePropertySourcerandom.*
  6. 打包 jar 外部的应用程序属性(包括 YAML 和配置文件变体)。application.properties
  7. 打包在 jar 中的应用程序属性(包括 YAML 和配置文件变体)。application.properties
  8. @PropertySource类上的注释。@Configuration
  9. 默认属性(使用 指定)。SpringApplication.setDefaultProperties

记下第 6 行和第 7 行 - 属性位于 jar 内的属性之上

据我所知,没有说明的,这可能是我困惑/问题的根源,是当你不使用JAR而是分解目录(因此.)时会发生什么。PropertiesLauncher

如果分解目录的行为与 JAR 中声明的行为一致,我希望 在 中声明的属性值将覆盖 中声明的任何相同名称,但情况似乎并非如此。/local/appname/dev/overrides/application.propertiesclasspath:application-dev.properties

从Spring-boot文档(附录C.4)中还提到了该属性,该属性被描述为“...[的]其他属性文件的位置,例如(默认为 )'。PropertiesLauncherloader.home/opt/app${user.dir}

所以我尝试使用 代替 ,但无济于事。loader.homespring.config.location

(更新:我也尝试过使用,我有两个注意事项:它似乎想要一个文件而不是一个目录(所以它的行为与)不同当我提供文件路径而不是父目录时,它仍然没有帮助。loader.config.locationspring.config.location

任何人都可以发现我做错了什么,或者我做了什么不正确的假设?


答案 1

谢谢,戴夫,你的建议是100%正确的。

如果我将属性文件重命名为,则该文件中的属性值覆盖 中的属性值。/local/appname/dev/overridesapplication-dev.propertiesclasspath:application-dev.properties

我确信我昨天已经尝试了这种组合,但我认为一定阻止它工作的是当我尝试指定并弄错了,所以它没有在正确的位置查找覆盖文件。spring.config.location


答案 2