概述
配置必须是环境特定的,这是生活的基本法则。如果不是这样,那就不再是配置,而是在代码中硬编码值。
对于Spring应用程序,有多种解决方案可供选择,从简单的解决方案到非常灵活、复杂的替代方案。
一个常见且直接的方法是灵活使用属性文件,以及Spring提供的第一级属性支持(如何使用属性文件)。
为了验证这个概念,本文将关注一种特定类型的属性——数据库配置。在生产环境中使用一种数据库配置,测试环境使用另一种,开发环境使用另一种,这完全合理。
2. 各个环境的*.properties*文件
让我们开始我们的验证概念:定义我们要针对的目标环境:
- 开发环境(Dev)
- 预发布环境(Staging)
- 生产环境(Production)
接下来,创建三个属性文件,每个环境一个:
- persistence-dev.properties
- persistence-staging.properties
- persistence-production.properties
在典型的Maven应用中,这些文件可以放在src/main/resources
目录下,但在部署时,它们需要在类路径上可访问。
重要的是要注意,所有属性文件都在版本控制下,使得配置更透明,可复现。这与仅仅将配置文件存储在磁盘上并指向它们的做法形成对比。
3. Spring配置
在Spring中,我们将根据环境包含正确的文件:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd">
<context:property-placeholder
location="
classpath*:*persistence-${envTarget}.properties" />
</beans>
同样,用Java配置也可以实现:
@PropertySource({ "classpath:persistence-${envTarget:dev}.properties" })
这种方法允许我们拥有多个\*.properties
文件,用于特定、专注的目的。例如,在我们的案例中,持久化Spring配置导入了持久性属性,这是合理的。安全性配置会导入与安全相关的属性等。
4. 在每个环境中设置属性
最终的可部署war包将包含所有属性文件——对于持久性,是三种变体的persistence-\*.properties
。由于文件实际上有不同的名称,不必担心意外包含错误的一个。我们将设置**envTarget
变量**,从而从多个现有变体中选择所需的实例。
envTarget
变量可以在操作系统或JVM命令行参数中设置:
-DenvTarget=dev
5. 测试和Maven
对于需要启用持久化的集成测试,我们将在pom.xml中设置envTarget
属性:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<systemPropertyVariables>
<envTarget>h2_test</envTarget>
</systemPropertyVariables>
</configuration>
</plugin>
对应的persistence-h2_test.properties
文件可以放在src/test/resources
下,这样它仅在测试时使用,不会在运行时无谓地包含和部署到war包中。
6. 进一步扩展
如果需要,可以采用几种方法为这个解决方案增加额外的灵活性。
一种方法是使用更复杂的文件名编码,不仅指定它们将使用的环境,还可以提供更多信息(如持久化提供者)。例如,我们可以使用以下类型的属性文件:persistence-h2.properties
、persistence-mysql.properties
,甚至更具体:persistence-dev_h2.properties
、persistence-staging_mysql.properties
、persistence-production_amazonRDS.properties
。
这种命名约定的优势——这只是约定,整体方法没有变化——在于透明度。只需查看文件名,现在就更容易理解配置的作用:
- persistence-dev_h2.properties:开发环境的持久化提供者是轻量级的内存H2数据库
- persistence-staging_mysql.properties:预发布环境的持久化提供者是MySQL实例
- persistence-production_amazon_rds.propertie:生产环境的持久化提供者是Amazon RDS
7. 总结
本文讨论了一种在Spring中进行环境特定配置的灵活解决方案。有关使用profile进行项目配置的另一种替代方案,请参阅此处。
该解决方案的实现可在GitHub项目中找到,这是一个基于Maven的项目,导入并运行起来应该很容易。