我正在开发一个Spring应用程序,我意识到我的管理属性的方式存在问题。 我使用Spring环境配置文件来加载我的属性,而且我最近添加了更多使我的属性文件无法管理的配置文件。
属性文件位于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;
}
...
}
总结一下,我的问题如下:
因此,我正在寻找一种新策略来管理不同环境之间的差异。
有人可以帮忙吗?
答案 0 :(得分:5)
有很多方法可以做到这一点,但我认为你走的是正确的道路。 覆盖属性文件是通过BeanFactoryPostProcessors完成的,在这种情况下有两个实现可以帮助你,所以你不必从头开始:
PropertySourcesPlaceholderConfigurer& 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>
在该示例中,您将默认属性加载到将用作其他bean的模板的bean中,并且在特定bean中,例如TestEnvironmentProperties Bean或DevEnvironmentProperties Bean,您只覆盖要从默认值覆盖的特定属性属性文件。该示例仅显示如何覆盖特定属性而无需创建另一个属性文件,从那里您可以决定如何选择使用工厂,简单外观类或配置文件系统创建的bean,您喜欢和匹配的任何内容架构。
此外,如果您认为此选项过于冗长,则可以使用property-placeholder元素。
我推荐你这本书:
Getting started with Spring Framework, Second Edition
它只有你在第5章中需要的例子。我没有写过它或者任何东西,我刚刚买了它,经过这么多糟糕的春季书后我很喜欢它。
答案 1 :(得分:2)
将公共属性拉入单独的文件中,并指定加上特定于配置文件的属性作为每个配置文件的输入。 Haven没有使用基于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>
答案 2 :(得分:0)
我想我偶然发现了这个问题的开始interesting blog post。
引用文章:
注意环境特定属性的冗余。例如, 如果解决方案是为每个环境都有一个属性文件 (例如“db-test.properties”,“db-dev.properties”等),然后 保持这些属性可能是一个噩梦 - 如果一个 属性“foo”被添加,然后它将被添加到 每个环境的属性文件(例如DEV,TEST,PROD等)。该 PropertyOverrideConfigurer适合消除这种情况 冗余,在应用程序上下文中设置默认值 本身,但随后在单独的文件中的重写值。它的 然而,重要的是记录这个,因为它可以看起来有点 对于看到一个价值的毫无戒心的维护开发人员来说,这是“神奇的” 在上下文文件中指定,但另一个在运行时使用。
我们的想法是依靠PropertyOverrideConfigurer并分解出常见的属性。
答案 3 :(得分:0)
更好的做法是将所有属性文件放在WAR包装之外。您可以使用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>
如果在Windows上,JNDI条目可能被指定为/ C / Users / someone。 最后,添加一个名为/opt/external/props/my-conf.properties的文件,并在其中放置一个条目,如:fooConfig.param1 = true
洗涤,冲洗,重复。更少的工作,更安全,更容易维护。
答案 4 :(得分:0)
我建议&#34;普通&#34;属性不需要在公共文件中,而是可以在代码中内联属性占位符的默认值。这允许它们通过JVM args(或本地环境)被覆盖,而不需要被管理&#34;在一个文件中。特定于环境的属性,在特定于环境的文件中,然后仅指示必须在每个环境中提供的应用程序启动的属性。因此,它们在占位符中没有默认值。