Существуют тонкие различия в том, как интерпретируется fileName
, который вы передаете. В основном, у вас есть 2 разных метода: ClassLoader.getResourceAsStream()
и Class.getResourceAsStream()
. Эти два метода найдут ресурс по-разному.
В Class.getResourceAsStream(path)
путь интерпретируется как локальный путь к пакету класса, из которого вы вызываете его. Например, String.getResourceAsStream("myfile.txt")
будет искать файл в вашем пути к классам в следующем месте: "java/lang/myfile.txt"
. Если ваш путь начинается с /
, то он будет считаться абсолютным путем и начнет поиск из корня пути к классам. Таким образом, вызов String.getResourceAsStream("/myfile.txt")
приведет к поиску следующего местоположения в вашем пути к классам ./myfile.txt
.
ClassLoader.getResourceAsStream(path)
будет считать все пути абсолютными. Поэтому вызовы String.getClassLoader().getResourceAsStream("myfile.txt")
и String.getClassLoader().getResourceAsStream("/myfile.txt")
будут искать файл в вашем classpath по следующему адресу: ./myfile.txt
.
Каждый раз, когда я упоминаю местоположение в этом посте, это может быть местоположение в самой вашей файловой системе или внутри соответствующего файла JAR, в зависимости от класса и / или ClassLoader, из которого вы загружаете ресурс.
В вашем случае вы загружаете класс с сервера приложений, поэтому вы должны использовать Thread.currentThread().getContextClassLoader().getResourceAsStream(fileName)
вместо this.getClass().getClassLoader().getResourceAsStream(fileName)
. this.getClass().getResourceAsStream()
тоже будет работать.
Прочтите эту статью для получения более подробной информации об этой конкретной проблеме.
Предупреждение для пользователей 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()
или Class.getResourceAsStream()
в версиях Tomcat более ранних, чем 8. И вы также должны помнить, что class.getResourceAsStream("/resource.txt")
на самом деле вызывает classLoader.getResourceAsStream("resource.txt")
(ведущий * 1054) * раздет).