Ada perbedaan halus tentang bagaimana fileName
Anda menyampaikan ditafsirkan. Pada dasarnya, Anda memiliki 2 metode berbeda: ClassLoader.getResourceAsStream()
dan Class.getResourceAsStream()
. Kedua metode ini akan menemukan sumber daya secara berbeda.
Di Class.getResourceAsStream(path)
, path ditafsirkan sebagai path lokal ke paket dari kelas yang Anda panggil. Misalnya panggilan, String.getResourceAsStream("myfile.txt")
akan mencari file di classpath Anda di lokasi berikut: "java/lang/myfile.txt"
. Jika path Anda dimulai dengan a /
, maka itu akan dianggap sebagai path absolut, dan akan mulai mencari dari akar classpath. Jadi panggilan String.getResourceAsStream("/myfile.txt")
akan melihat lokasi berikut di jalur kelas Anda ./myfile.txt
.
ClassLoader.getResourceAsStream(path)
akan menganggap semua jalur sebagai jalur absolut. Jadi menelepon String.getClassLoader().getResourceAsStream("myfile.txt")
dan String.getClassLoader().getResourceAsStream("/myfile.txt")
akan baik mencari file di classpath Anda di lokasi berikut: ./myfile.txt
.
Setiap kali saya menyebutkan lokasi dalam posting ini, itu bisa menjadi lokasi di sistem file Anda sendiri, atau di dalam file jar yang sesuai, tergantung pada Kelas dan / atau ClassLoader tempat Anda memuat sumber daya.
Dalam kasus Anda, Anda memuat kelas dari Application Server, sehingga Anda harus menggunakan Thread.currentThread().getContextClassLoader().getResourceAsStream(fileName)
bukan this.getClass().getClassLoader().getResourceAsStream(fileName)
. this.getClass().getResourceAsStream()
juga akan bekerja.
Baca artikel ini untuk informasi lebih rinci tentang masalah khusus itu.
Peringatan untuk pengguna Tomcat 7 dan di bawah
Salah satu jawaban untuk pertanyaan ini menyatakan bahwa penjelasan saya tampaknya tidak benar untuk Tomcat 7. Saya sudah mencoba melihat-lihat untuk melihat mengapa itu akan terjadi.
Jadi saya telah melihat kode sumber Tomcat WebAppClassLoader
untuk beberapa versi Tomcat. Implementasi findResource(String name)
(yang sepenuhnya bertanggung jawab untuk menghasilkan URL ke sumber daya yang diminta) sebenarnya identik dalam Tomcat 6 dan Tomcat 7, tetapi berbeda dalam Tomcat 8.
Dalam versi 6 dan 7, implementasi tidak berusaha untuk menormalkan nama sumber. Ini berarti bahwa dalam versi-versi ini, classLoader.getResourceAsStream("/resource.txt")
mungkin tidak menghasilkan hasil yang sama seperti classLoader.getResourceAsStream("resource.txt")
peristiwa meskipun seharusnya (karena apa yang ditentukan oleh Javadoc). [Kode sumber]
Namun dalam versi 8, nama sumber dinormalisasi untuk menjamin bahwa versi absolut dari nama sumber adalah yang digunakan. Oleh karena itu, dalam Tomcat 8, dua panggilan yang dijelaskan di atas harus selalu mengembalikan hasil yang sama. [Kode sumber]
Akibatnya, Anda harus ekstra hati-hati saat menggunakan ClassLoader.getResourceAsStream()
atau Class.getResourceAsStream()
pada versi Tomcat lebih awal dari 8. Dan Anda juga harus ingat bahwa class.getResourceAsStream("/resource.txt")
panggilan sebenarnya classLoader.getResourceAsStream("resource.txt")
(pemimpin /
dilucuti).
getClass().getResourceAsStream("/myfile.txt")
berperilaku berbeda darigetClassLoader().getResourceAsStream("/myfile.txt")
.