application.properties 是否可以依赖多个配置文件?
Is it possible to have application.properties depend on multiple profiles?
是否可以让 Spring 引导属性文件依赖于两个或多个配置文件?类似于 application-profile1-profile2.properties
?
Spring Boot 不支持开箱即用。它仅支持描述的单个配置文件 here.
但是,它确实提供了足够的灵活性,可以使用 EnvironmentPostProcessor 添加您自己的 属性 源。
下面是一个如何实现这个的例子:
public class MultiProfileEnvironmentPostProcessor implements EnvironmentPostProcessor, Ordered {
private final ResourceLoader resourceLoader = new DefaultResourceLoader();
@Override
public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
String[] activeProfiles = environment.getActiveProfiles();
for (int i = 2; i <= activeProfiles.length; i++) {
Generator.combination(activeProfiles).simple(i)
.forEach(profileCombination -> {
String propertySourceName = String.join("-", profileCombination);
String location = "classpath:/application-" + propertySourceName + ".properties";
if (resourceLoader.getResource(location).exists()) {
try {
environment.getPropertySources().addFirst(new ResourcePropertySource(propertySourceName, location));
} catch (IOException e) {
throw new RuntimeException("could not add property source '" + propertySourceName + "'", e);
}
}
});
}
}
@Override
public int getOrder() {
return Ordered.LOWEST_PRECEDENCE;
}
}
有两点需要注意:
- 此实现仅支持
.properties
个文件,但也可以轻松扩展到 .yml
个文件。
- getActiveProfiles 已经 returns 配置文件中最后一个获胜的顺序。此实现依赖于此顺序并利用此顺序构建不同的文件名。即,如果活动配置文件是:profile1、profile2、profile3,则支持
application-profile1-profile3.properties
但不支持 application-profile3-profile1.properties
,并且 application-profile1-profile3.properties
将覆盖 application-profile1.properties
或 [=17= 中定义的属性].
- 此实现使用第三方库
com.github.dpaukov:combinatoricslib3
来创建不同的配置文件集。
- 属性 源被添加到 属性 源列表的前面以覆盖现有源。但是,如果您有自定义的 属性 源应该优先,您需要稍微修改一下以按顺序考虑它们,即利用
Environment.addAfter
. 等方法
- 使用
spring.factories
文件注册 EnvironmentPostProcessor。
我知道的方法有 4 种。
像 Asi Bross Said 一样以编程方式插入 .yaml
或 .properties
。使用ResourceLoader
或YamlPropertySourceLoader插入。
使用.yaml
。但是当你有另一个 spring 项目依赖它时它会被替换。
使用属性而不是配置文件。 (对于 api 项目)
- 使用一个
@PropertySource
定义属性文件A.
- 从属性文件 A 中获取变量并将它们分配给另一个
@PropertySource
文件路径表达式中的参数。
例如:
resources
/-application.properties <-- remove or empty,because it will be override by application project
/-moduleA
/-application.properties <-- Intellij can identify properties files started with application-
/-application-mysql-dev.properties
/-application-psql-dev.properties
/-application-psql-prod.properties
resources/moduleA/application.properties
内容:
moduleA.custom.profile1=mysql
moduleA.custom.profile2=dev
Java 配置文件的内容:
@SpringBootApplication
@PropertySources({
@PropertySource("/moduleA/application.properties"),
@PropertySource("/moduleA/application-${moduleA.custom.profile1}-${moduleA.custom.profile2}.properties"),
})
public class ModuleConfig {}
使用属性而不是配置文件。 (申请项目)
resources
/-application.properties
/-application-mysql-dev.properties
/-application-psql-dev.properties
/-application-psql-prod.properties
resources/application.properties
的内容:
moduleA.custom.profile1=mysql
moduleA.custom.profile2=dev
SpringMvcApplication.java
的内容:
@SpringBootApplication
@PropertySource("/application-${moduleA.custom.profile1}-${moduleA.custom.profile2}.properties")
public class SpringMvcApplication {...}
是否可以让 Spring 引导属性文件依赖于两个或多个配置文件?类似于 application-profile1-profile2.properties
?
Spring Boot 不支持开箱即用。它仅支持描述的单个配置文件 here.
但是,它确实提供了足够的灵活性,可以使用 EnvironmentPostProcessor 添加您自己的 属性 源。
下面是一个如何实现这个的例子:
public class MultiProfileEnvironmentPostProcessor implements EnvironmentPostProcessor, Ordered {
private final ResourceLoader resourceLoader = new DefaultResourceLoader();
@Override
public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
String[] activeProfiles = environment.getActiveProfiles();
for (int i = 2; i <= activeProfiles.length; i++) {
Generator.combination(activeProfiles).simple(i)
.forEach(profileCombination -> {
String propertySourceName = String.join("-", profileCombination);
String location = "classpath:/application-" + propertySourceName + ".properties";
if (resourceLoader.getResource(location).exists()) {
try {
environment.getPropertySources().addFirst(new ResourcePropertySource(propertySourceName, location));
} catch (IOException e) {
throw new RuntimeException("could not add property source '" + propertySourceName + "'", e);
}
}
});
}
}
@Override
public int getOrder() {
return Ordered.LOWEST_PRECEDENCE;
}
}
有两点需要注意:
- 此实现仅支持
.properties
个文件,但也可以轻松扩展到.yml
个文件。 - getActiveProfiles 已经 returns 配置文件中最后一个获胜的顺序。此实现依赖于此顺序并利用此顺序构建不同的文件名。即,如果活动配置文件是:profile1、profile2、profile3,则支持
application-profile1-profile3.properties
但不支持application-profile3-profile1.properties
,并且application-profile1-profile3.properties
将覆盖application-profile1.properties
或 [=17= 中定义的属性]. - 此实现使用第三方库
com.github.dpaukov:combinatoricslib3
来创建不同的配置文件集。 - 属性 源被添加到 属性 源列表的前面以覆盖现有源。但是,如果您有自定义的 属性 源应该优先,您需要稍微修改一下以按顺序考虑它们,即利用
Environment.addAfter
. 等方法
- 使用
spring.factories
文件注册 EnvironmentPostProcessor。
我知道的方法有 4 种。
像 Asi Bross Said 一样以编程方式插入
.yaml
或.properties
。使用ResourceLoader
或YamlPropertySourceLoader插入。使用
.yaml
。但是当你有另一个 spring 项目依赖它时它会被替换。使用属性而不是配置文件。 (对于 api 项目)
- 使用一个
@PropertySource
定义属性文件A. - 从属性文件 A 中获取变量并将它们分配给另一个
@PropertySource
文件路径表达式中的参数。
例如:
resources /-application.properties <-- remove or empty,because it will be override by application project /-moduleA /-application.properties <-- Intellij can identify properties files started with application- /-application-mysql-dev.properties /-application-psql-dev.properties /-application-psql-prod.properties
resources/moduleA/application.properties
内容:moduleA.custom.profile1=mysql moduleA.custom.profile2=dev
Java 配置文件的内容:
@SpringBootApplication @PropertySources({ @PropertySource("/moduleA/application.properties"), @PropertySource("/moduleA/application-${moduleA.custom.profile1}-${moduleA.custom.profile2}.properties"), }) public class ModuleConfig {}
- 使用一个
使用属性而不是配置文件。 (申请项目)
resources /-application.properties /-application-mysql-dev.properties /-application-psql-dev.properties /-application-psql-prod.properties
resources/application.properties
的内容:moduleA.custom.profile1=mysql moduleA.custom.profile2=dev
SpringMvcApplication.java
的内容:@SpringBootApplication @PropertySource("/application-${moduleA.custom.profile1}-${moduleA.custom.profile2}.properties") public class SpringMvcApplication {...}