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

标签 java properties spring-boot overriding

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

我有一个自动配置的 Spring-boot 应用程序(即使用 @EnableAutoconfiguration ),它有多个配置文件,我使用 PropertiesLauncher 启动。而不是 JarLauncher (与部署限制有关的原因 - 我需要将分解的目录而不是存档部署到 只读 文件系统中。)

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

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.bar ,以及声明一个新属性,foo.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.password ,属性(property)不是 application-dev.properties 中声明文件 拿起,覆盖foo.bar被忽略 - 我仍然看到值,baz来自 application-dev.properties而不是值,overridden-value来自 /local/appname/dev/overrides/application.properties .

--debug选项已启用,我可以看到 ConfigFileApplicationListener记录它已经加载了覆盖文件(来自文件系统)和特定于配置文件的文件(来自类路径),按此顺序 .

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

Spring-boot 文档非常具体地说明了为 Spring-boot 可执行 JAR 解析属性的顺序,按优先级降序排列:
  • 命令行参数。
  • Java 系统属性 ( System.getProperties() )。
  • 操作系统环境变量。
  • 来自 java:comp/env 的 JNDI 属性
  • A RandomValuePropertySource仅在 random.* 中具有属性.
  • 应用属性 打包的 jar( application.properties 包括 YAML 和配置文件变体)。
  • 应用程序属性打包 您的 jar( application.properties 包括 YAML 和配置文件变体)。
  • @PropertySource您的 @Configuration 上的注释类。
  • 默认属性(使用 SpringApplication.setDefaultProperties 指定)。

  • 注意第 6 行和第 7 行 - 属性 在属性你的 jar 。

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

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

    在 Spring-boot 文档(PropertiesLauncher 上的附录 C.4)中还提到了 loader.home属性,它被描述为 '... [the] 附加属性文件的位置,例如/opt/app (默认为 ${user.dir} )'。

    所以我尝试使用 loader.home而不是 spring.config.location ,但无济于事。

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

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

    最佳答案

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

    如果我重命名 /local/appname/dev/overrides 中的属性文件至 application-dev.properties然后是该文件中的属性值 覆盖 classpath:application-dev.properties 中的那些.

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

    关于java - 使用 PropertiesLauncher 启动的 Spring-boot(特定于配置文件)应用程序中的问题覆盖应用程序属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26662381/

    相关文章:

    java - 我应该使用什么作为返回语句?

    java - 将 DLL 导入 Eclipse Java 项目

    python - 如何拥有默认对象属性并可以选择设置它?

    java - spring-rabbit 中的 ClassNotFoundException 取决于消费者或生产者何时启动

    Java Spring : Real-time status update to the client over REST API

    java - 在 Android App 和 Google AppEngine 之间共享 Android 库

    java - 突破游戏(当我出局时,我希望球再次击中剩余的砖 block )

    c# - 如何在 C# 类中拥有父属性?

    java - 从 IDE 和 JAR 外部加载 .properties 文件

    java - redis.clients.jedis.exceptions.JedisConnectionException : Could not get a resource from the pool