Spring 为开发和部署加载不同的属性
我有一个非常常见的用例——当我的程序处于开发模式、测试模式或部署模式时,连接到不同的数据库 我现在的做法是配置一个数据源,并通过bean:property标记传递${…}属性 然而,为了得到${…},我正在做Spring 为开发和部署加载不同的属性,spring,properties-file,spring-environment,Spring,Properties File,Spring Environment,我有一个非常常见的用例——当我的程序处于开发模式、测试模式或部署模式时,连接到不同的数据库 我现在的做法是配置一个数据源,并通过bean:property标记传递${…}属性 然而,为了得到${…},我正在做 <context:property-placeholder properties-ref="myProperties" /> 在xml配置的底部,我有 <beans profile=test> <util:properties id=myPropert
<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>
这似乎效率低下,过于冗长,而且容易出错。所有SpringProperties教程都告诉我context:PropertyPlaceholder是环境感知的,环境负责配置文件,所以如何简化它?直觉告诉我有一个更简单的方法,我就是想不出来
实际上,我想要的是在context:properties占位符或类似的内容上指定profile。在Spring支持profiles之前很久,我就解决了这个问题: 现在a仍然使用属性文件,但是,我会按配置文件选择它们。有很多方法可以做到这一点: 最简单的是:
<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>
第一种方法有一个缺点,当激活多个概要文件时,只有第一个概要文件的属性被加载。我不确定当有多个配置文件时,第二种方法会发生什么
对于我发现的第一种方法,但我尚未对其进行测试:
<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>
虽然概要文件无疑是解决这个问题的一种方法,但我认为这种方法为您仅在目标平台上发现的问题打开了另一扇大门 在我的项目中,我总是将属性外部化,并将尽可能多的属性转换为运行时参数 想象一下,由于您的平台不属于类路径中包含属性的概要文件,因此不得不再次捆绑Jenkins/Sonar/etc。我不认为这些项目会成功 至于spring,您可以在PropertyConfigure中使用'file://'协议,允许超级种子来自类路径的dedault属性。因此,您有两个带有order参数和其他属性的configurer标记。下面是一个例子:
<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文件
在属性中,我们定义了在运行时无法更改的所有参数,这些参数基本上是Hibernate参数和其他一些参数
其余的都作为简单的系统参数键值对存储在数据库中。有许多属性不需要修复。这包括:LDAP、MailSender、tempdir等文件夹定义
由于datasource是最早启动的Bean之一,因此在我目前运行的项目中效果非常好,而且我们仍在发现更多要推送到数据库中的属性。请阅读:
在这里,个人资料绝对是一个不错的选择。使用JavaConfig也很容易做到同样的事情。配置文件可以在不改变war的情况下切换either@doom777. 是的,但是为什么要限制自己使用预定义的值呢?我说的是属性,不是豆子。想象一下这样一种情况:您有一个定义了数据源的生产概要文件。无论出于何种原因,数据库会移动,连接字符串也会更改。您必须更新您的个人资料并重新创建战争。
<context:property-placeholder location="
classpath:application.properties,
classpath:application${spring.profiles.active}.properties"
ignore-unresolvable="true"/>
mvn clean install -Dspring.profiles.active="profile_name".