从不同位置加载属性

时间:2013-07-28 21:12:06

标签: java maven properties configuration

我正在努力寻找一种解决方案来根据不同的环境(devprod)从不同的地方访问配置文件。

这是我项目的近似布局。

   │   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);

以下是几个问题:

  1. 我应该如何将环境变量传递给Maven的代码(在配置文件或其他内容中定义)?我不想过滤java类,并且可能只使用环境条目预加载另一个属性文件。另外,我认为我无法在生产平台上修改系统属性(-Denv=whatever)。

  2. 如果属性文件需要包含其他系统组件要访问的某些资源的路径(例如,applicationContext.xml对于spring,它也应该位于dev的类路径中,或者bin tomcat的文件夹)?这些路径应该是什么样子,我将如何在我的代码中解决它们,避免代码重复ConfigurationLoader部分?

  3. 是否有机会在maven中解决更多问题,在代码中解决更少问题,或者存在其他方法?

2 个答案:

答案 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类。 然后,每种不同类型的实例都可以使用其他属性来决定要加载哪个资源。