【问题标题】:Loading properties from different locations从不同位置加载属性
【发布时间】:2013-07-28 14:07:02
【问题描述】:

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

这是我项目的大致布局。

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

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

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

对于这种选择性的属性加载,如何正确实现ConfigurationLoader

谢谢

UPD:

我对@9​​87654330@ 实现和属性文件的位置更感兴趣。问题是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 部分的代码重复?

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

【问题讨论】:

  • 你不能定义两种环境并用 if 语句检查你当时正在使用什么环境吗?这可能在您的设置文件或类似文件中。

标签: java maven properties configuration


【解决方案1】:

喜欢这个问题!我们遇到了完全相同的问题,并按如下方式解决。我们项目的结构基本相同,只是多了一个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 配置文件或应用程序服务器的 lib 目录中包含的 conf.properties,并用 conf.properties 中的属性覆盖在 conf.default.properies 中找到的所有现有属性。

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

希望这会有所帮助:)

【讨论】:

  • +1 击败了我。配置文件是要走的路。它们可以在 POM 中声明,也可以在外部设置文件中声明并按需启用。另一个例子见:stackoverflow.com/questions/15120229/…
  • 您好,感谢您的回答。请参阅我上面的更新以获得更多描述性评论。
【解决方案2】:

虽然可能有多种解决方案,但我更喜欢以下解决方案:

使用两个实现相同接口的不同类(例如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 类。 然后,每种不同类型的实例都可以使用附加属性来决定要加载哪个资源。

【讨论】:

  • 嗨,谢谢,这是我目前的解决方案,但是从该属性文件中引用其他资源存在问题。我想我需要以 ConfigurationLoader 的几种实现方式重复加载这些资源。查看我的更新
猜你喜欢
  • 2013-12-02
  • 2010-11-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多