在如何实现这一点上存在细微的差别fileName
你正在传递被解释。基本上,你有两种不同的方法:ClassLoader.getResourceAsStream()
and Class.getResourceAsStream()
。这两种方法将以不同的方式定位资源。
In Class.getResourceAsStream(path)
,该路径被解释为您从中调用它的类的包的本地路径。例如调用,String.class.getResourceAsStream("myfile.txt")
将在类路径中的以下位置查找文件:"java/lang/myfile.txt"
。如果您的路径以/
,那么它将被认为是绝对路径,并且将从类路径的根开始搜索。所以打电话String.class.getResourceAsStream("/myfile.txt")
将查看类路径中的以下位置./myfile.txt
.
ClassLoader.getResourceAsStream(path)
会将所有路径视为绝对路径。所以打电话String.class.getClassLoader().getResourceAsStream("myfile.txt")
and String.class.getClassLoader().getResourceAsStream("/myfile.txt")
都会在类路径中的以下位置查找文件:./myfile.txt
.
每次我在这篇文章中提到一个位置时,它可能是文件系统本身中的位置,也可能是相应 jar 文件中的位置,具体取决于您从中加载资源的类和/或类加载器。
在您的情况下,您正在从应用程序服务器加载该类,因此您应该使用Thread.currentThread().getContextClassLoader().getResourceAsStream(fileName)
代替this.getClass().getClassLoader().getResourceAsStream(fileName)
. this.getClass().getResourceAsStream()
也会起作用。
Read 本文有关该特定问题的更多详细信息。
Tomcat 7 及以下版本用户的警告
这个问题的答案之一指出我的解释对于 Tomcat 7 似乎是不正确的。我试图环顾四周看看为什么会出现这种情况。
于是我查看了Tomcat的源代码WebAppClassLoader
适用于 Tomcat 的多个版本。实施findResource(String name)
(最终负责生成所请求资源的 URL)在 Tomcat 6 和 Tomcat 7 中几乎相同,但在 Tomcat 8 中有所不同。
在版本 6 和 7 中,实现不会尝试标准化资源名称。这意味着在这些版本中,classLoader.getResourceAsStream("/resource.txt")
可能不会产生相同的结果classLoader.getResourceAsStream("resource.txt")
尽管它应该发生(因为 Javadoc 指定了)。[源代码]
但在版本 8 中,资源名称已标准化,以保证所使用的资源名称的绝对版本。因此,在 Tomcat 8 中,上述两个调用应始终返回相同的结果。[源代码]
因此,使用时必须格外小心ClassLoader.getResourceAsStream()
or Class.getResourceAsStream()
在早于 8 的 Tomcat 版本上。并且您还必须记住class.getResourceAsStream("/resource.txt")
实际上打电话classLoader.getResourceAsStream("resource.txt")
(领先的/
被剥离)。