有什么区别:
InputStream is = this.getClass().getClassLoader().getResourceAsStream(fileName)
和
InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream(fileName)
InputStream is = this.getClass().getResourceAsStream(fileName)
什么时候每一个都比其他的更适合使用?
我要读取的文件作为读取文件的类位于类路径中。我的类和文件在同一个 jar 中并打包在一个 EAR 文件中,并部署在 WebSphere 6.1 中。
fileName关于您传递的内容的解释方式存在细微差别。基本上,您有 2 种不同的方法:ClassLoader.getResourceAsStream()和Class.getResourceAsStream(). 这两种方法将以不同的方式定位资源。
fileName
ClassLoader.getResourceAsStream()
Class.getResourceAsStream()
在Class.getResourceAsStream(path)中,路径被解释为您从中调用它的类的包的本地路径。例如调用,String.class.getResourceAsStream("myfile.txt")将在您的类路径中的以下位置查找文件:"java/lang/myfile.txt". 如果您的路径以 a 开头/,那么它将被视为绝对路径,并将从类路径的根目录开始搜索。因此,调用String.class.getResourceAsStream("/myfile.txt")将查看您的类路径中的以下位置./myfile.txt。
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")andString.class.getClassLoader().getResourceAsStream("/myfile.txt")都会在您的类路径中的以下位置查找文件:./myfile.txt.
ClassLoader.getResourceAsStream(path)
String.class.getClassLoader().getResourceAsStream("myfile.txt")
String.class.getClassLoader().getResourceAsStream("/myfile.txt")
每次我在这篇文章中提到一个位置时,它可能是您的文件系统本身中的一个位置,也可能是相应的 jar 文件中的一个位置,具体取决于您从中加载资源的类和/或类加载器。
在您的情况下,您正在从应用程序服务器加载类,因此您应该使用Thread.currentThread().getContextClassLoader().getResourceAsStream(fileName)而不是this.getClass().getClassLoader().getResourceAsStream(fileName). this.getClass().getResourceAsStream()也将工作。
Thread.currentThread().getContextClassLoader().getResourceAsStream(fileName)
this.getClass().getClassLoader().getResourceAsStream(fileName)
this.getClass().getResourceAsStream()
阅读本文以获取有关该特定问题的更多详细信息。
这个问题的答案之一表明我的解释对于 Tomcat 7 似乎是不正确的。我试图环顾四周,看看为什么会出现这种情况。
所以我查看了 Tomcat 的WebAppClassLoader几个版本的 Tomcat 的源代码。Tomcat 6 和 Tomcat 7的实现findResource(String name)(最终负责生成请求资源的 URL)实际上是相同的,但在 Tomcat 8 中是不同的。
WebAppClassLoader
findResource(String name)
在版本 6 和 7 中,实现不会尝试规范化资源名称。这意味着在这些版本中,classLoader.getResourceAsStream("/resource.txt")可能不会产生与事件相同的结果,classLoader.getResourceAsStream("resource.txt")尽管它应该(因为 Javadoc 指定)。[源代码]
classLoader.getResourceAsStream("/resource.txt")
classLoader.getResourceAsStream("resource.txt")
但是在版本 8 中,资源名称被规范化以保证资源名称的绝对版本是使用的那个。因此,在 Tomcat 8 中,上述两个调用应该总是返回相同的结果。[源代码]
因此,在使用 Tomcat 8 之前的版本时,您必须格外小心ClassLoader.getResourceAsStream()。Class.getResourceAsStream()并且您还必须记住class.getResourceAsStream("/resource.txt")实际调用classLoader.getResourceAsStream("resource.txt")(前导/被剥离)。
class.getResourceAsStream("/resource.txt")