正确使用Spring环境配置文件以管理PropertySourcesPlaceholderConfigurer和属性文件集
我正在开发一个Spring应用程序,我意识到我管理属性的方式有问题我使用Spring环境配置文件来加载我的属性,最近我添加了更多配置文件,这使得我的属性文件无法管理 属性文件位于正确使用Spring环境配置文件以管理PropertySourcesPlaceholderConfigurer和属性文件集,spring,environment-variables,properties-file,spring-profiles,Spring,Environment Variables,Properties File,Spring Profiles,我正在开发一个Spring应用程序,我意识到我管理属性的方式有问题我使用Spring环境配置文件来加载我的属性,最近我添加了更多配置文件,这使得我的属性文件无法管理 属性文件位于src/main/resources/META-INF/props/中的不同文件夹中,eah文件夹与不同的Spring环境概要文件匹配 我现在至少有5个配置文件,这意味着我有5个子文件夹,每个子文件夹包含具有相同名称但的属性文件,并且只有一些键的值不同 下面是它的外观: 以下是我如何配置PropertyPlacehol
src/main/resources/META-INF/props/
中的不同文件夹中,eah文件夹与不同的Spring环境概要文件匹配
我现在至少有5个配置文件,这意味着我有5个子文件夹,每个子文件夹包含具有相同名称但的属性文件,并且只有一些键的值不同
下面是它的外观:
以下是我如何配置PropertyPlaceholders的:
@Configuration
public class PropertyPlaceholderConfiguration {
@Profile(Profiles.CLOUD)
static class cloudConfiguration {
@Bean
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() throws IOException {
PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer = new PropertySourcesPlaceholderConfigurer();
propertySourcesPlaceholderConfigurer.setIgnoreUnresolvablePlaceholders(Boolean.TRUE);
propertySourcesPlaceholderConfigurer.setLocations(new PathMatchingResourcePatternResolver().getResources("classpath*:META-INF/props/cloud/*.properties"));
return propertySourcesPlaceholderConfigurer;
}
}
@Profile(Profiles.DEFAULT)
static class defaultConfiguration {
@Bean
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() throws IOException {
PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer = new PropertySourcesPlaceholderConfigurer();
propertySourcesPlaceholderConfigurer.setIgnoreUnresolvablePlaceholders(Boolean.TRUE);
propertySourcesPlaceholderConfigurer.setLocations(new PathMatchingResourcePatternResolver().getResources("classpath*:META-INF/props/default/*.properties"));
return propertySourcesPlaceholderConfigurer;
}
}
@Profile(Profiles.TEST)
static class testConfiguration {
@Bean
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() throws IOException {
PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer = new PropertySourcesPlaceholderConfigurer();
propertySourcesPlaceholderConfigurer.setIgnoreUnresolvablePlaceholders(Boolean.TRUE);
propertySourcesPlaceholderConfigurer.setLocations(new PathMatchingResourcePatternResolver().getResources("classpath*:META-INF/props/test/*.properties"));
return propertySourcesPlaceholderConfigurer;
}
}
@Profile(Profiles.DEV)
static class devConfiguration {
@Bean
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() throws IOException {
PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer = new PropertySourcesPlaceholderConfigurer();
propertySourcesPlaceholderConfigurer.setIgnoreUnresolvablePlaceholders(Boolean.TRUE);
propertySourcesPlaceholderConfigurer.setLocations(new PathMatchingResourcePatternResolver().getResources("classpath*:META-INF/props/dev/*.properties"));
return propertySourcesPlaceholderConfigurer;
}
...
}
总而言之,我的问题如下:
- 键/值对在5个不同的文件夹中重复,因为只有少数值不同李>
有人可以帮忙吗?将公共属性拉入一个单独的文件,并指定该文件加上特定于配置文件的属性作为每个配置文件的输入。我没有使用基于Java的Spring配置,但下面是我在XML中的实现方式。假设您可以在代码中执行相同的操作:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">
<beans profile="default">
<bean id="applicationPropertiesPlaceholder"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:profiles/common.profile.properties</value>
<value>classpath:profiles/local.profile.properties</value>
</list>
</property>
</bean>
</beans>
<beans profile="local">
<bean id="applicationPropertiesPlaceholder"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:profiles/common.profile.properties</value>
<value>classpath:profiles/local.profile.properties</value>
</list>
</property>
</bean>
</beans>
<beans profile="trial">
<bean id="applicationPropertiesPlaceholder"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:profiles/common.profile.properties</value>
<value>classpath:profiles/trial.profile.properties</value>
</list>
</property>
</bean>
</beans>
<beans profile="live">
<bean id="applicationPropertiesPlaceholder"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:profiles/common.profile.properties</value>
<value>classpath:profiles/live.profile.properties</value>
</list>
</property>
</bean>
</beans>
</beans>
类路径:profiles/common.profile.properties
类路径:profiles/local.profile.properties
类路径:profiles/common.profile.properties
类路径:profiles/local.profile.properties
类路径:profiles/common.profile.properties
类路径:profiles/trial.profile.properties
类路径:profiles/common.profile.properties
类路径:profiles/live.profile.properties
我想我偶然发现了这个解决方案的开始
引自文章:
注意环境特定属性的冗余。例如
如果解决方案是每个环境有一个属性文件
(例如,“db测试属性”、“db-dev.properties”等),然后
维护这些属性可能有点像噩梦——如果
如果添加了属性“foo”,则必须将其添加到
每个环境的属性文件(例如开发、测试、产品等)。这个
PropertyOverrideConfiguler适用于消除此问题
冗余,在应用程序上下文中设置默认值
本身,但覆盖值在单独的文件中。它是
然而,很重要的一点是,要记录好这一点,因为它看起来有点像
对于一个看到一个价值的毫无戒心的维护开发人员来说是“神奇的”
在上下文文件中指定,但在运行时使用另一个
我们的想法是依靠并排除共同属性。有很多方法可以做到这一点,但我认为您走的是正确的道路。 属性文件的重写是通过BeanFactoryPostProcessors完成的,在这种情况下,有两种实现可以帮助您,因此您不必从头开始: PropertySourcePlaceHolderConfigurer和PropertyOverrideConfigurer 这是一个使用PropertySourcesPlaceholderConfigurer的示例:
<bean id="someProperties" class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer" abstract="true" >
<property name="locations">
<list>
<value>classpath:database.properties</value>
<value>classpath:email.properties</value>
</list>
</property>
<property name="ignoreUnresolvablePlaceholders" value="false"/>
</bean>
<bean id="devProperties" parent="someProperties" >
<property name="properties" >
<props >
<prop key="database.username">Database Username used for Development Environment </prop>
</props>
</property>
<property name="localOverride" value="true" />
</bean>
<bean id="testProperties" parent="someProperties" >
<property name="properties" >
<props >
<prop key="database.username">Database Username used for Testing Environment </prop>
</props>
</property>
<property name="localOverride" value="true" />
</bean>
classpath:database.properties
类路径:email.properties
用于开发环境的数据库用户名
用于测试环境的数据库用户名
在该示例中,您将默认属性加载到一个bean中,该bean将用作其他bean的模板,在特定bean中,例如TestenEnvironmentProperties bean或DevenEnvironmentProperties bean,您只覆盖您要从默认属性文件覆盖的特定属性。该示例仅显示了如何覆盖特定属性,而无需创建另一个属性文件,从中您可以决定如何选择使用工厂、简单门面类或概要文件系统创建哪个bean,以及您喜欢并匹配您的体系结构的任何内容
此外,如果您认为此选项过于冗长,则可以使用元素
我向你推荐这本书:
在它的第五章中,有一些你需要的例子。我没有写它或其他什么,我只是在一段时间前买了它,在读了这么多糟糕的春季书籍后,我很喜欢它。更好的做法是将所有属性文件放在战争包装之外。您可以使用JNDI变量将Spring指向可以读取外部属性文件的物理路径。例如:
<jee:jndi-lookup id="externalFileArea" jndi-name="java:comp/env/mgo/externalFileArea"
default-value="/opt/external/props" lookup-on-startup="true"/>
<util:properties id="myConf" location="file:#{externalFileArea}/my-conf.properties"/>
<!-- And now, to use an entry from this properties import -->
<bean id="foo" class="foo.bar.com">
<property name="configParam1" value="#{myConf['fooConfig.param1']}"
</bean>
我建议“common”属性不需要在公共文件中,而是可以是代码中内嵌的属性占位符的默认值。这允许通过JVM参数(或本地环境)覆盖它们,而不需要在文件中进行“管理”。然后在特定于环境的文件中指定每个环境中必须提供的属性,以便启动应用程序。因此,它们在占位符中不会有默认值。谢谢!嗯,唯一的问题是,您的解决方案强制一个在同一个文件中具有不相关的属性(即common.profile.properties)…建议解决方案的另一个问题是,如果出于某种原因,在某一点上我需要一个属性的不同值,我需要将其从c中拉出