一尘不染

通过在同一容器中运行多个应用程序来使Spring Boot中的配置外部化

spring-boot

我正在构建多个Spring Boot应用程序,这些应用程序将部署在同一servlet容器中。但是我很难让Spring
Boot以我想要的方式而不是框架想要的方式与外部化的配置文件一起工作。

情况:

  • 多个Spring Boot应用程序将部署在单个servlet容器(WAR文件)上
  • 配置文件的位置将通过JVM属性设置 spring.config.location
  • 嵌入式部署不是一种选择

问题:

由于将应用程序部署在同一JVM上,因此该属性spring.config.location对于所有应用程序都具有相同的值。我希望我们的所有应用程序都使用相同的配置文件命名(application.properties),所以指定spring.config.name不是选项。

我想要的是:

  • 无需设置,spring.config.name因为我们所有应用程序中的配置名称都应标准化(恒定)
  • 外部化的配置属性应覆盖我部署的WAR中打包的application.properties中的值
  • 特定于配置文件的配置(application- {profile})应该可行
  • 代码中没有硬编码的配置位置
  • 按应用程序目录布局组织配置文件:

$ {spring.config.location} /app1/application.properties $
{spring.config.location} /app2/application.properties $
{spring.config.location} /app3/application.properties

问题:

是否有某种机制可以影响或覆盖外部配置文件的加载或解析?

还有其他方法来获得预期的结果吗?


阅读 553

收藏
2020-05-30

共1个答案

一尘不染

@Iulian
Rosca建议使用像这样的模式,这${properties_home}/${application_id}/application.properties使我想到了定义像这样的自定义JVM属性的想法,app.config.root并使用此属性spring.config.location在应用程序生命周期的早期覆盖了它。

我的应用程序类现在看起来像这样,并适用于嵌入式和容器部署:

@SpringBootApplication
public class Application extends SpringBootServletInitializer {

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
        return configureApplication(builder);
    }

    public static void main(String[] args) {
        configureApplication(new SpringApplicationBuilder()).run(args);
    }

    private static SpringApplicationBuilder configureApplication(SpringApplicationBuilder builder) {
        return builder
            .sources(Application.class)
            .properties("spring.config.location:${${app.config.root}/myapp1/:#{null}}");
    }

}

此解决方案的重要说明:

  • app.config.root 必须通过JVM或JNDI属性在外部设置
  • app.config.root只能指定一个外部配置路径(对于我的要求,这已经足够了),而spring.config.location可以指定多个逗号分隔的路径
  • SpringApplicationBuilder.properties(...)设置应用程序的默认属性。因此,spring.config.location无法再在外部进行指定,因为JVM或JNDI属性的优先级高于默认属性,因此将被spring.config.location再次覆盖。
2020-05-30