我正在努力寻找一种解决方案来根据不同的环境(dev
,prod
)从不同的地方访问配置文件。
这是我项目的近似布局。
│ pom.xml
└───src
└───main
├───java
│ ConfigurationLoader.java
├───resources
│ conf1.properties
└───webapp
│ web.xml
└───WEB-INF
ConfigurationLoader
是一个自我描述的类,应该是一些普通的单例,在整个应用程序中静态可用。
在dev
环境中,它应该从类路径根加载conf1.properties
,但在prod
env中它应该在容器的根文件夹中找到它们(例如%TOMCAT_HOME%\bin
)。< / p>
如何正确实施ConfigurationLoader
这种选择性属性加载?
由于
的 UPD: 的
我对ConfigurationLoader
实现和属性文件位置更感兴趣。问题是ConfigurationLoader
如何定位这些文件。类似的东西:
String path = "/conf1.properties";
File confFile;
switch (environment) {
case "dev": //classpath
URI location = ConfigurationLoader.class.getResource(path).toURI();
confFile = new File(location);
break;
case "prod": //root (?)
confFile = new File(path);
break;
}
Properties p = new Properties(confFile);
以下是几个问题:
我应该如何将环境变量传递给Maven的代码(在配置文件或其他内容中定义)?我不想过滤java类,并且可能只使用环境条目预加载另一个属性文件。另外,我认为我无法在生产平台上修改系统属性(-Denv=whatever
)。
如果属性文件需要包含其他系统组件要访问的某些资源的路径(例如,applicationContext.xml
对于spring,它也应该位于dev
的类路径中,或者bin
tomcat的文件夹)?这些路径应该是什么样子,我将如何在我的代码中解决它们,避免代码重复ConfigurationLoader
部分?
是否有机会在maven中解决更多问题,在代码中解决更少问题,或者存在其他方法?
答案 0 :(得分:2)
喜欢这个问题!我们遇到了完全相同的问题,并按如下方式解决了问题。除了额外的external-resources-{username}
文件夹外,我们项目的结构基本相同:
│ pom.xml
└───src
└───main
├───java
│ ConfigurationLoader.java
├───external-resources-drvdijk
│ conf.properties
├───resources
│ conf.default.properties
└───webapp
│ web.xml
└───WEB-INF
然后,在pom.xml
中,我们包括:
<profiles>
<profile>
<id>development</id>
<build>
<resources>
<resource>
<directory>src/main/external-resources-${user.name}</directory>
<filtering>true</filtering>
</resource>
</resources>
</build>
</profile>
</profiles>
这使每个团队成员都可以创建自己的external-resources-{username}
目录,启用Maven配置文件并构建。
我们的ConfigurationLoader.java
版本(实际上在我们的项目中实际上称为不同版本)将首先读取conf.default.properties
文件中的所有属性(它们也可能是“空”属性,例如db.username =
) 。然后,它将加载Maven配置文件或应用程序服务器的conf.properties
目录中包含的lib
,并覆盖conf.default.properies
中找到的所有现有属性和{{1}中找到的属性}}
在我们的conf.properties
中,我们明确列出了我们的应用程序可以处理的所有属性。如果在加载所有属性(包括conf.default.properties
)后,有些属性丢失(或者找到了一些未知的属性),则应用程序会引发很多错误并拒绝启动。
希望这会有所帮助:)
答案 1 :(得分:1)
虽然有各种各样的解决方案,但我更喜欢以下方法:
使用两个实现相同接口的不同类(例如ConfigurationLoader
接口),一个用于处理类路径配置的类,另一个用于处理文件大小写。使用由您的构建创建的应用程序的属性文件(例如app.properties)(prod和dev的不同值),并始终位于类路径中的相同位置,例如根包。在此文件中,您将拥有以下属性:
config.loader.class=com.mycompany.ClasspathConfigurationLoader # or FileConfigurationLoader for prod environment
config.loader.resource.classpath=resources/conf1.properties # use classloader.getResourceAsStream() to load this resource
config.loader.resource.file=/path/to/tomcat/home/bin/conf1.properties
现在,由于您的加载器是单例,您将拥有一个静态块,该块将读取属性文件,并根据第一个属性决定要创建哪个类型的实例作为ConfigurationLoader
类。
然后,每种不同类型的实例都可以使用其他属性来决定要加载哪个资源。