Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
正确使用Spring环境配置文件以管理PropertySourcesPlaceholderConfigurer和属性文件集_Spring_Environment Variables_Properties File_Spring Profiles - Fatal编程技术网

正确使用Spring环境配置文件以管理PropertySourcesPlaceholderConfigurer和属性文件集

正确使用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

我正在开发一个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;
        }
     ...
    }
总而言之,我的问题如下:

  • 键/值对在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中拉出