【问题标题】:not able to load properties file with runnable jar无法使用可运行的 jar 加载属性文件
【发布时间】:2015-09-14 05:52:34
【问题描述】:

我在 Java 中有一个 maven 项目,其中我在这个目录下有一个属性文件 (quartz.properties):

/src/main/resources

现在我可以从这个类中以两种方式使用这个属性文件,如下所示:

/**
 * Create a StdSchedulerFactory that has been initialized via
 * <code>{@link #initialize(Properties)}</code>.
 *
 * @see #initialize(Properties)
 */
public StdSchedulerFactory(Properties props) throws SchedulerException {
    initialize(props);
}

/**
 * Create a StdSchedulerFactory that has been initialized via
 * <code>{@link #initialize(String)}</code>.
 *
 * @see #initialize(String)
 */
public StdSchedulerFactory(String fileName) throws SchedulerException {
    initialize(fileName);
}

所以我开始这样使用:

public static void main(String[] args) {
    StdSchedulerFactory factory = new StdSchedulerFactory();
    try {
        factory.initialize(TestClassName.class.getClassLoader().getResourceAsStream("quartz.properties"));
        Scheduler scheduler = factory.getScheduler();
        scheduler.start();
    } catch (SchedulerException ex) {
        System.out.println("error= " + ExceptionUtils.getStackTrace(ex));
    }
}

这在我的 Windows 笔记本电脑上运行良好,没有任何问题,但是当我制作一个可运行的 jar(导出 --> 可运行的 jar --> 将所需的库打包到生成的 JAR 中),然后如果我在我的其他 ubuntu 机器上像这样运行:

java -jar abc.jar

我遇到了这个异常:

error= org.quartz.SchedulerException: Error loading property data from InputStream - InputStream is null.
        at org.quartz.impl.StdSchedulerFactory.initialize(StdSchedulerFactory.java:576)
        at com.example.quartz.TestClassName.main(TestClassName.java:17)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:601)
        at org.eclipse.jdt.internal.jarinjarloader.JarRsrcLoader.main(JarRsrcLoader.java:58)

我做错了什么?

更新:- 来自 jar tvf abc.jar 的输出。我只是展示相关的东西而不是全部。

    13 Thu Sep 10 18:16:30 GMT-07:00 2015 resources/build.properties
   594 Thu Sep 10 18:16:30 GMT-07:00 2015 resources/quartz.properties
  1254 Thu Sep 10 18:16:30 GMT-07:00 2015 resources/quartz_config.xml

【问题讨论】:

  • 您确定是quartz.properties 而不是Quartz.properties?你能运行jar tvf abc.jar 并显示输出吗?
  • 为什么要使用 IDE 创建 jar 文件,而不是使用 Maven?
  • @JonSkeet 是的,它是quartz.properties。我可以在我的笔记本电脑上清楚地看到它,并且它在本地运行良好。同时更新问题。
  • @JBNizet 我已经使用了很长时间了,所以想像这样使用它。如果我需要通过 maven 使用它,那么只需运行 mvn clean install 并使用来自maven.repo的jar?
  • 现在你已经发布了,很简单...

标签: java maven properties classloader quartz-scheduler


【解决方案1】:

您的文件在 jar 文件中为 resources/quartz.properties,而不仅仅是 quartz.properties - 这就是您需要加载它的方式:

factory.initialize(
  TestClassName.class.getClassLoader().getResourceAsStream("resources/quartz.properties"));

或者,以不同的方式创建 jar 文件,使 quartz.properties 位于 jar 文件的“根”目录中。 (鉴于您所描述的文件系统结构,这正是我所期望的。)

【讨论】:

  • 感谢您的解释。我怎样才能使这个通用 - 这意味着每当我在本地运行它时它应该自动运行,并且每当我在我的 ubuntu 机器中将它作为java -jar abc.jar 的可运行 jar 运行时,它应该也能正常运行。每当我可以制作 jar 文件时,是否有任何通过 maven 可以为我做的更好的方法?
  • @user1950349:正如我在答案中所说,您可以更改文件在资源文件中的最终位置 - 当您将资源添加到 jar 文件时,添加 resources 目录的内容作为根元素,而不是添加 resources 目录本身。
  • 好的明白,但我该怎么做呢?我以前从未这样做过。是通过 eclipse(我在这里使用的)还是其他方式?
  • @user1950349:您可能想要移动 resources 目录(例如,作为顶级目录)或将其添加为 Eclipse 中的资源根目录,或者更改打包 jar 的方式文件。有关详细信息,请阅读有关“将所需库打包到生成的 JAR”的文档。
【解决方案2】:

如果您想从您的班级访问resources/build.properties,您需要使用绝对路径,如下所示:

TestClassName.class.getClassLoader().getResourceAsStream("/resources/quartz.properties")

【讨论】:

  • 在资源前使用斜线会改变类路径,并且不会搜索项目中的属性。正如@Jon skeet 提到的那样,它应该用作'TestClassName.class.getClassLoader().getResourceAsStream("resources/quartz.properties")'。
  • 取决于您的TestClassName 的包。我提到的是资源的绝对路径。如果删除斜杠,则它是类包中的相对路径。如果它在默认包中,两者都是相同的。但是如果你的TestClassName 在包foo 中,资源路径将变为`/foo/...'。
【解决方案3】:

首先你应该确保 jar 文件中的quartz.properties。如果不存在,则需要检查 pom.xml 中的构建设置

【讨论】:

    猜你喜欢
    • 2018-01-08
    • 1970-01-01
    • 1970-01-01
    • 2013-11-06
    • 2012-07-24
    • 1970-01-01
    • 1970-01-01
    • 2016-05-03
    • 2017-04-30
    相关资源
    最近更新 更多