Існують тонкі відмінності щодо того, як fileNameінтерпретується ваш передач. В основному у вас є два різні методи: ClassLoader.getResourceAsStream()і Class.getResourceAsStream(). Ці два методи по-різному знайдуть ресурс.
В Class.getResourceAsStream(path), шлях трактується як локальний шлях до пакету класу, з якого ви викликаєте. Наприклад , покликанням, String.getResourceAsStream("myfile.txt")буде шукати файл у вашому шляху до класів за наступною адресою: "java/lang/myfile.txt". Якщо ваш шлях починається з значка a /, він вважатиметься абсолютним шляхом і почне пошук з кореня classpath. Таким чином, дзвінок String.getResourceAsStream("/myfile.txt")буде розглядати наступне місце на шляху вашого класу ./myfile.txt.
ClassLoader.getResourceAsStream(path)вважатиме всі шляхи абсолютними. Так виклику String.getClassLoader().getResourceAsStream("myfile.txt")і String.getClassLoader().getResourceAsStream("/myfile.txt")обидва будуть шукати файл у вашому шляху до класів за наступною адресою: ./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")(ведучий /позбавлений).
getClass().getResourceAsStream("/myfile.txt")поводиться інакшеgetClassLoader().getResourceAsStream("/myfile.txt").