【问题标题】:Loading an external properties file in sibling directory在同级目录中加载外部属性文件
【发布时间】:2012-03-18 04:07:20
【问题描述】:

以下场景

./
 config/
    application.properties
 lib/
    properties-loader-0.0.1-SNAPSHOT.jar
 acme.sh

properties-loader-0.0.1-SNAPSHOT.jar 是一个带有清单文件的可执行 jar。 jar 中有一个包com.acme.lab,只包含类 具有完全限定名称com.acme.lab.PropertiesLoader

脚本acme.sh执行如下命令:

java -cp etc/application.properties:./lib/properties-loader-0.0.1-SNAPSHOT.jar com.acme.lab.PropertiesLoader

我正在尝试从PropertiesLoader 类访问属性文件。我读了Smartly load your properties的文章,但仍然无法访问属性文件

System.out.println(this.getClass().getResourceAsStream("../etc/application.properties"));
System.out.println(this.getClass().getResourceAsStream("etc/application.properties"));
System.out.println(this.getClass().getResourceAsStream("/etc/application.properties"));
System.out.println(this.getClass().getResourceAsStream("application.properties"));

System.out.println(this.getClass().getClassLoader().getResourceAsStream("../etc/application.properties"));
System.out.println(this.getClass().getClassLoader().getResourceAsStream("etc/application.properties"));
System.out.println(this.getClass().getClassLoader().getResourceAsStream("/etc/application.properties"));
System.out.println(this.getClass().getClassLoader().getResourceAsStream("application.properties"));

try {
    System.out.println(ResourceBundle.getBundle("etc.application"));
    System.out.println(ResourceBundle.getBundle("application"));
} catch(MissingResourceException e) {
    // do nothing
}

所有这些调用都无法加载文件。

我只知道错误与类路径有关,但似乎找不到。我在 github 创建了一个示例 maven 项目,它重现了问题。

【问题讨论】:

  • @drhirsch 我认为标签maven-assembly-plugin 在这种情况下可能比assemblies 更合适。
  • 当然,将其更改为您认为合适的 - 但 assembly 和以前一样,是错误的。事实上,正是这个标签把我带到了这里——它是关于机器代码的。每个标签都有一个描述 - 如果您不确定,请阅读它。
  • 忘了我可以自己改。感谢您的提示。

标签: java maven properties classpath maven-assembly-plugin


【解决方案1】:

资源是从它们的类路径根中解释的。当你像这样运行你的程序时,你的情况是:

java -cp etc/application.properties:./lib/properties-loader-0.0.1-SNAPSHOT.jar

根是

  • ./etc/application.properties
  • ./lib/properties-loader-0.0.1-SNAPSHOT.jar

其中都不包含您的 application.properties 文件(作为子资源)。如果你像这样修改你的命令:

java -cp etc:./lib/properties-loader-0.0.1-SNAPSHOT.jar

然后你可以在你的程序中读取你的属性文件:

Thread.currentThread().getContextClassLoader().getResourceAsStream("application.properties");

附带说明,最好在类路径设置中使用完全限定路径。


* 编辑 *

这是一个可以说明资源加载的工作示例:

mkdir props; cd props
mkdir etc; touch etc/application.properties
mkdir test; vi test/PropLoader.java

将此内容粘贴到编辑器中然后保存:

package test;

import java.io.InputStream;

public class PropLoader {
   public static void main(String[] args) {
      try {
         final String path;
         if(args.length == 1) path = args[0].trim();
         else path = "etc/application.properties";

         final InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream(path);
         if(is == null) throw new RuntimeException("Failed to load " + path + " as a resource");
         else System.out.printf("Loaded resource from path: %s\n", path);
      } catch(Exception e) {
         e.printStackTrace();
      }
   }
}

然后进行测试:

javac test/PropLoader.java
java -cp . test.PropLoader

输出是Loaded resource from path: etc/application.properties

【讨论】:

  • 我是否正确理解类路径参数应该只包含路径和罐子,以便可以从那里加载子资源?我也 tried 你的解决方案,但它仍然得到 null 作为 InputStream。
  • 是的,你的类路径应该只包含paths 和档案(罐子)。我编辑了我的答案,以包含一个如果您准确遵循应该可以工作的示例。
  • 我可以效仿你。感谢您的澄清。
  • 我在生产中仍然遇到问题,ContextClassCloader 失败,而SystemClassLoader 工作。会不会是某个组件替代了 ClassLoader?
猜你喜欢
  • 2011-08-27
  • 2013-01-28
  • 2017-07-25
  • 1970-01-01
  • 2014-12-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-04-15
相关资源
最近更新 更多