我有一个非常常见的用例 - 当我的程序处于开发模式,测试模式或部署模式时连接到不同的数据库。
我现在的方式是配置数据源,并通过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或类似的东西。
答案 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)
请阅读:
<context:property-placeholder location="
classpath:application.properties,
classpath:application${spring.profiles.active}.properties"
ignore-unresolvable="true"/>
mvn clean install -Dspring.profiles.active="profile_name".