资源在导出为JAR文件时无法加载。

huangapple go评论73阅读模式
英文:

Resource won't load when exported as a JAR

问题

使用以下代码来设置系统属性:

ClassLoader classLoader = StartMain.class.getClassLoader();

URL resource = classLoader.getResource("com/myname/lib/chromedriver/chromedriver.exe");

File f = new File("Driver");

if (!f.exists()) {
    f.mkdirs();
}

File chromeDriver = new File("Driver" + File.separator + "chromedriver.exe");

if (!chromeDriver.exists()) {
    chromeDriver.createNewFile();
    org.apache.commons.io.FileUtils.copyURLToFile(resource, chromeDriver);
}

这在我在我的IDE IntelliJ中运行应用程序配置时效果完美。然而,当我构建一个JAR文件并尝试在IntelliJ之外使用它时,资源URL返回为null。为什么会这样?

英文:

Using the following code to set a system property:


    ClassLoader classLoader = StartMain.class.getClassLoader();

    URL resource = classLoader.getResource("com/myname/lib/chromedriver/chromedriver.exe");

    File f = new File("Driver");

    if (!f.exists()) {

        f.mkdirs();

    }

    File chromeDriver = new File("Driver" + File.separator + "chromedriver.exe");

    if (!chromeDriver.exists()) {

        chromeDriver.createNewFile();

        org.apache.commons.io.FileUtils.copyURLToFile(resource, chromeDriver);

    }

This works perfectly when I run my application configuration in my IDE, IntelliJ. However, when I build a JAR and attempt to use this outside of IntelliJ, the resource URL returns as null. Why is this so?

答案1

得分: 2

通过您的类加载器进行操作是有风险的。这可能无法解释您的问题,但也可能有用;无论如何,采用这种替代方法更短、更简单、更符合习惯,在所有您的操作起作用的地方都有效,并且在更多地方也有效:

获取此类资源的最佳方法如下:

StartMain.class.getResource("/com/myname/lib/chromedriver/chromedriver.exe");

注意,这个路径以斜杠开头!如果不指定的话,这个风格会基于您自己的类文件位置(基本上是您的包)。

无论哪种形式,都会在与 StartMain.class 相同的 JAR 文件中查找条目:

/com/myname/lib/chromedriver/chromedriver.exe

如果它不在那里,这显然不会起作用 - 请修复您的构建以包含它。在“运行时”,某个文件夹可能位于类路径上,可以解析此文件;如果在构建过程中未将该文件夹合并到 JAR 文件中,那就能解释为什么在 IDE 中可以工作,但在其他地方无法工作。

注意:通常不需要任何 Apache 工具。例如,有 InputStreamtransferTo 方法,也可以将此操作变为一行代码(改用 getResourceAsStream 进行获取)。

英文:

Going via your classloader is risky. It probably doesn't explain your problem but it might; in any case, this alternative way to do it is shorter, simpler, more idiomatic, works in all places your take works, and works in more places to boot:

The best way to fetch resources like this is like so:

StartMain.class.getResource("/com/myname/lib/chromedriver/chromedriver.exe");

Note that this one starts with a slash! This style goes relative to your own class file location (your package, basically) if you don't.

Either form will look for the entry:

/com/myname/lib/chromedriver/chromedriver.exe

inside the same jar that StartMain.class lives. If it is not there, then this obviously won't work - fix your build so that it is included. At 'runtime' some folder may be on the classpath that would resolve this file; if that folder is then not folded into you jar during the build, that would explain why it works within the IDE but not elsewhere.

NB: You generally don't need any apache utils. For example, there's InputStream's transferTo which can make this a one-liner too (fetch getResourceAsStream instead).

huangapple
  • 本文由 发表于 2020年8月26日 09:38:31
  • 转载请务必保留本文链接:https://go.coder-hub.com/63589303.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定