我正在使用@PropertySource 和@ConfigurationProperties 的组合,但我想用外部属性文件覆盖它们

Posted

技术标签:

【中文标题】我正在使用@PropertySource 和@ConfigurationProperties 的组合,但我想用外部属性文件覆盖它们【英文标题】:I am using a combination of @PropertySource and @ConfigurationProperties but I want to overwrite them with an external properties file 【发布时间】:2018-04-13 00:36:57 【问题描述】:

我已经建立了一个spring boot项目。

在其中,我有一个如下所示的属性类:

@Configuration
@PropertySource(value = "classpath:abc.properties")
@ConfigurationProperties
public class ABCProperties 

    private Map<String, String> someUrls;

    @Bean
    public Map<String, String> someUrls() 
        return someUrls;
    

    public Map<String, String> getSomeUrls() 
        return someUrls;
    

    public void setSomeUrls(Map<String, String> someUrls) 
        this.someUrls = someUrls;
    

abc.properties 文件的内容如下所示:

someUrls.urlA=someURL
someUrls.urlB=someOtherURL

在项目的资源文件夹(和测试资源文件夹)中,我提供了一个 abc.properties 文件。构建并运行后,程序可以按预期访问 abc.properties 文件中的属性(也可以在测试中正确访问)-它们很好地映射到我的 url 映射。

到目前为止一切顺利。

但是,我在属性类中引用的 URL 并不总是相同的。在某些部署中,我想覆盖它们。使用我的 application.properties 文件中指定的属性,这很容易;只需在我运行应用程序的同一(根)文件夹中拥有另一个外部 application.properties 文件,就会自动覆盖我放入其中的任何属性。

有时我想做的是将外部 abc.properties 文件放在应用程序的根文件夹中,并让它以相同的方式覆盖 abc.properties 属性。当然我试过了,但是 内置到 jar 中的 abc.properties 文件中的属性被保留而不被覆盖。事实上,我根本不确定spring boot程序是否识别出它的根文件夹中还有另一个外部的abc.properties文件。

我似乎没完没了地阅读了如何在没有成功的情况下实现这一目标。我也尝试在我的 application.properties 中指定以下内容,但没有任何区别(即使它确实有效,它也不理想,因为我宁愿在所有情况下都不指定直接路径)。

spring.config.location=/path/to/application/root/
spring.config.name=abc.properties

如果我不得不猜测,问题是在属性类中我指向“类路径:..”,而外部文件实际上不在类路径上,因为它是....很好的外部文件。

但是 spring boot 知道如何在其根应用程序文件夹中查找覆盖的 application.properties,所以我希望它也能够查找要覆盖的其他属性文件?我只是无法理解如何实现这一目标。

是的,我特别希望我的属性在这个 abc.properties 文件中,而不是在应用程序属性中。

【问题讨论】:

文档是here。 【参考方案1】:

你看过PropertySources吗?

@PropertySources(
    @PropertySource("classpath:abc.properties"),
    @PropertySource(value="file:abc.properties", ignoreResourceNotFound=true)
)

来自他们的文档:

如果给定的属性键存在于多个 .properties 文件中,则处理的最后一个 @PropertySource 注释将“获胜”并覆盖。

基本上你在这里说的是:从类路径加载 abc.properties,但也从这个外部位置加载 abc.properties,如果找不到,则忽略后者。它应该覆盖您在外部文件中声明的属性。

还没有测试过,希望能成功。

【讨论】:

您先生,是个绅士。这正是我一直在尝试做的。我已经看到了多个属性源选项,但我认为它适用于不同的属性文件,而不是不同位置的同一个文件。非常感谢! @sfat 我已经创建了多模块 spring 项目,我正在尝试测试一个模块。我的 application.properties 文件位于根文件夹中。所以我必须在 PropertiesSource 值中硬编码文件路径。还有其他方法吗? @Sumeet_Pol 在你的情况下它不像 @PropertySource("classpath:/abc.properties") 那样工作吗?

以上是关于我正在使用@PropertySource 和@ConfigurationProperties 的组合,但我想用外部属性文件覆盖它们的主要内容,如果未能解决你的问题,请参考以下文章

在 Spring Cloud Config 中使用 @PropertySource - Git

@Import 覆盖 Spring @PropertySource

使用带有外部 JSON 文件的 @PropertySource 的 Spring 属性配置

使用 @PropertySource 将 .properties 文件中的所有值注入属性(或映射)

引导 PropertySource 排序

如何创建依赖于 Spring Bean 的自定义 Spring PropertySource