1

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

这是我的项目的大致布局。

   │   pom.xml
   └───src
       └───main
           ├───java
           │       ConfigurationLoader.java
           ├───resources
           │       conf1.properties
           └───webapp
               │   web.xml
               └───WEB-INF

ConfigurationLoader是一个自我描述的类,应该是一些普通的单例,在整个应用程序中静态可用。

在环境中它应该从类路径根dev加载,但在环境中它应该在容器的根文件夹中找到它们(例如)。conf1.propertiesprod%TOMCAT_HOME%\bin

如何ConfigurationLoader正确实现这种选择性属性加载?

谢谢

升级版:

我对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或该bintomcat 的文件夹中)怎么办?这些路径应该是什么样子,我需要如何在我的代码中解决它们以避免该ConfigurationLoader部分的代码重复?

是否有机会在 Maven 中更多地解决它而在代码中更少地解决它,或者存在哪些其他方法?

4

2 回答 2

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 =)。然后,它将加载conf.propertiesMaven 配置文件或应用程序服务器lib目录中包含的 ,并conf.default.properiesconf.properties.

我们conf.default.properties明确列出了我们的应用程序可以处理的所有属性。如果在加载完所有属性(包括conf.properties)后,一些属性丢失(或发现了一些未知属性),应用程序将引发大量错误并拒绝启动。

希望这可以帮助 :)

于 2013-07-28T22:52:00.903 回答
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类。然后,每种不同类型的实例都可以使用附加属性来决定要加载哪个资源。

于 2013-07-28T21:53:45.137 回答