为开发和部署加载不同的属性

时间:2014-07-20 08:21:40

标签: spring properties-file spring-environment

我有一个非常常见的用例 - 当我的程序处于开发模式,测试模式或部署模式时连接到不同的数据库。

我现在的方式是配置数据源,并通过bean:property标签传递$ {...}属性。

然而要获得$ {...},我正在做

<context:property-placeholder properties-ref="myProperties" />

在xml配置的底部,我有

<beans profile=test>
   <util:properties id=myProperties>
   </util>
</beans>
<beans profile=dev,default>
   <util:properties id=myProperties>
</beans>
<beans profile=prod>
  <util:properties id="myProperties>
</beans>

这似乎效率低下,过于冗长,容易出错。所有spring属性教程都告诉我上下文:property-placeholder是环境感知的,而Environment负责配置文件,所以我该如何简化呢?对我来说直观的是,有一种更简单的方法,我无法弄明白。

真的,我要找的是在上下文中指定配置文件:properties-placeholder或类似的东西。

3 个答案:

答案 0 :(得分:3)

我解决了这个问题一次(很久以前Spring支持配置文件):spring property substitution for test and production

现在仍然会使用属性文件但是,我会按配置文件选择它们。有很多方法可以做到这一点:

最简单的是:

<context:property-placeholder
         location="classpath*:META-INF/spring/config-${spring.profiles.active}.properties" />

另一个是:

<beans profile="normal">
    <context:property-placeholder 
             location="classpath*:META-INF/spring/config-normal.properties"/>
</beans>
<beans profile="test">    
      <context:property-placeholder
             location="classpath*:META-INF/spring/config-test.properties"/>
</beans>

第一种方法的缺点是,当激活多个配置文件时,只会加载第一个配置文件的属性。我不确定当有多个配置文件时,第二种方法会发生什么。

对于第一种方法,我发现this solution,但我没有测试过它:

<bean id="propertyConfigurer"
      class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
      <property name="locations">
        <list>
            <value>classpath*:META-INF/spring/*_${spring.profiles.active}.properties</value>
        </list>
      </property>
</bean>

答案 1 :(得分:0)

虽然配置文件肯定是该问题的解决方案,但我认为这种方法为您在目标平台上发现的问题打开了另一扇大门。

在我的项目中,我总是将属性外部化,并将尽可能多的属性转换为运行时参数。

想象一下,必须再次捆绑Jenkins / Sonar / etc,因为您的平台不会成为属性驻留在类路径中的配置文件的一部分。我不认为那些是成功的项目;)

至于spring,你可以在propertyconfigurer中使用'file://'协议,允许取代来自类路径的“dedault”属性。因此,您有两个带有订单参数和其他属性的配置器标记。这是一个例子:

    <jee:jndi-lookup id="configDirectory" jndi-name="configDirectory"
    resource-ref="true" default-value="." />
<jee:jndi-lookup id="datasource" jndi-name="jdbc/datasource"
    expected-type="javax.sql.DataSource" default-ref="localDatasource" />

<!-- Allows fetching properties from multiple locations: -->
<!-- external definition -> file://${configDirectory}/root-context.properties 
    -> declared in context.xml -->
<!-- standard web application bundle -> /WEB-INF/spring/root-context.properties -->
<!-- testing -> classpath:root-context.properties -->
<context:property-placeholder location="${configDirectory:.}/context.properties"
    order="9" ignore-resource-not-found="true" ignore-unresolvable="true" />
<context:property-placeholder
    location="/WEB-INF/spring/context.properties,
    classpath:context.properties"
    order="10" ignore-resource-not-found="true" ignore-unresolvable="true" />
<context:property-placeholder location="classpath:spring/default.properties"
    order="100" />

像这样我们可以在本地构建它,在maven构建期间运行我们的单元和集成测试,在UAT上运行构建,如果一切正常,则可以将构建从UAT复制到PROD而无需修改war文件。 / p>

在属性中我们定义了所有在运行时无法更改的参数,这些参数本质上是Hibernate参数加上其他参数。

所有其余的都作为简单的系统参数(键值对)存储在数据库中。有许多属性不需要修复。这包括:LDAP,MailSender,文件夹定义,如tempdir等。

由于数据源是最初要启动的bean之一,因此我在当前运行的项目中工作得非常好,而且我们仍然发现要将更多属性推送到数据库中。

答案 2 :(得分:0)

请阅读:

https://examples.javacodegeeks.com/enterprise-java/spring/load-environment-configurations-and-properties-with-spring-example/

<context:property-placeholder  location="
       classpath:application.properties,
        classpath:application${spring.profiles.active}.properties"
                                      ignore-unresolvable="true"/>

mvn clean install -Dspring.profiles.active="profile_name".