web-dev-qa-db-ja.com

PropertySourcesPlaceholderConfigurerとプロパティファイルのセットを管理するために、Spring環境プロファイルを正しく使用する

私はSpringアプリケーションに取り組んでいて、プロパティの管理方法に問題があることに気づきました。 プロパティをロードするためにSpring環境プロファイルを使用し、最近、プロパティファイルを管理しにくくするプロファイルを追加しました

プロパティファイルはsrc/main/resources/META-INF/props/内の別のフォルダーにあり、eahフォルダーは別のSpring環境プロファイルと一致しています。

現在、少なくとも5つのプロファイルがあります。つまり、それぞれに同じ名前のプロパティファイルを含む5つのサブフォルダーがあります一部のキーのみに異なる値を使用

これがどのように見えるかです:

properties file screen capture

以下は、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つの異なるフォルダー全体で複製されます。

したがって、私は異なる環境間の違いを管理するための新しい戦略を探しています。

誰か助けてくれますか?

14
balteo

これを行うには多くの方法がありますが、私はあなたが正しい道にいると思います。プロパティファイルのオーバーライドはBeanFactoryPostProcessorsを介して行われます。この場合に役立つ2つの実装があるため、最初から行う必要はありません。

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 要素を使用できます。

私はこの本をお勧めします:

Spring Frameworkの第2版の概要

第5章では、必要な例を示しています。私はそれを書いたり何もしなかった、私は少し前にそれを買ったばかりで、たくさんの悪い春の本を読んだ後、それを愛した。

5
Langley

共通のプロパティを別のファイルにプルし、それに加えてプロファイル固有のプロパティを各プロファイルの入力として指定します。 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
Alan Hay

すべてのプロパティファイルを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

洗浄、すすぎ、繰り返し。作業がはるかに少なく、安全性が高く、保守がはるかに簡単です。

0
Jim Doyle

私はこの 興味深いブログ投稿 で解決策の始まりに偶然出会ったと思います。

記事から引用するには:

環境固有のプロパティの冗長性に注意してください。たとえば、ソリューションが環境ごとに1つのプロパティファイル(たとえば、「db-test.properties」、「db-dev.properties」など)を持つことである場合、これらのプロパティの維持は少し悪夢になる可能性があります。プロパティ「foo」が追加された場合は、各環境(DEV、TEST、PRODなど)のプロパティファイルに追加する必要があります。 PropertyOverrideConfigurerは、この冗長性を排除して、アプリケーションコンテキスト自体にデフォルト値を設定し、その後、別のファイルにオーバーライド値を設定するのに適しています。ただし、コンテキストファイルで指定された1つの値が実行時に使用される別の値を見る無防備なメンテナンス開発者にとっては少し「不思議」に見える可能性があるため、これを文書化することは重要です。

アイデアは、 PropertyOverrideConfigurer に依存し、共通のプロパティを除外することです。

0
balteo

「共通」プロパティは共通ファイルにある必要はなく、代わりにコード内のプロパティプレースホルダのデフォルト値にすることができます。これにより、JVM引数(またはローカル環境)を介してオーバーライドすることができ、ファイルで「管理」する必要はありません。環境固有のファイル内の環境固有のプロパティは、アプリを起動するために各環境で提供する必要があるプロパティのみを示します。そのため、プレースホルダーにデフォルト値はありません。

0
Michael Andrews