英文:
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 工具。例如,有 InputStream
的 transferTo
方法,也可以将此操作变为一行代码(改用 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).
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论