Existem diferenças sutis no modo como o que fileName
você está passando é interpretado. Basicamente, você tem 2 métodos diferentes: ClassLoader.getResourceAsStream()
eClass.getResourceAsStream()
. Esses dois métodos localizarão o recurso de maneira diferente.
Em Class.getResourceAsStream(path)
, o caminho é interpretado como um caminho local para o pacote da classe da qual você está chamando. Por exemplo chamada, String.getResourceAsStream("myfile.txt")
irá procurar um arquivo no seu classpath, no seguinte local: "java/lang/myfile.txt"
. Se o seu caminho começar com a /
, será considerado um caminho absoluto e começará a pesquisar a partir da raiz do caminho de classe. Assim, a chamada String.getResourceAsStream("/myfile.txt")
examinará o seguinte local no caminho da sua classe ./myfile.txt
.
ClassLoader.getResourceAsStream(path)
considerará todos os caminhos como absolutos. Então, chamando String.getClassLoader().getResourceAsStream("myfile.txt")
e String.getClassLoader().getResourceAsStream("/myfile.txt")
ambos procurarão um arquivo no seu caminho de classe no seguinte local:./myfile.txt
.
Toda vez que eu menciono um local neste post, ele pode ser um local no seu próprio sistema de arquivos ou dentro do arquivo jar correspondente, dependendo da Class e / ou ClassLoader da qual você está carregando o recurso.
No seu caso, você está carregando a classe de um servidor de aplicativos, portanto, você deve usar em Thread.currentThread().getContextClassLoader().getResourceAsStream(fileName)
vez de this.getClass().getClassLoader().getResourceAsStream(fileName)
. this.getClass().getResourceAsStream()
também irá funcionar.
Leia este artigo para obter informações mais detalhadas sobre esse problema específico.
Aviso para usuários do Tomcat 7 e abaixo
Uma das respostas a esta pergunta afirma que minha explicação parece incorreta para o Tomcat 7. Tentei procurar ao redor para ver por que esse seria o caso.
Então, eu olhei o código fonte do Tomcat WebAppClassLoader
para várias versões do Tomcat. A implementação de findResource(String name)
(que é totalmente responsável por produzir a URL para o recurso solicitado) é praticamente idêntica no Tomcat 6 e no Tomcat 7, mas é diferente no Tomcat 8.
Nas versões 6 e 7, a implementação não tenta normalizar o nome do recurso. Isso significa que nessas versões, classLoader.getResourceAsStream("/resource.txt")
pode não produzir o mesmo resultado que o classLoader.getResourceAsStream("resource.txt")
evento que deveria (desde que o Javadoc especifique). [Código fonte]
Na versão 8, porém, o nome do recurso é normalizado para garantir que a versão absoluta do nome do recurso seja a usada. Portanto, no Tomcat 8, as duas chamadas descritas acima sempre devem retornar o mesmo resultado. [Código fonte]
Como resultado, você deve ter um cuidado extra ao usar ClassLoader.getResourceAsStream()
ou Class.getResourceAsStream()
nas versões do Tomcat anteriores a 8. E você também deve ter em mente que, class.getResourceAsStream("/resource.txt")
na verdade, chama classLoader.getResourceAsStream("resource.txt")
(o líder /
é removido).
getClass().getResourceAsStream("/myfile.txt")
se comporta de maneira diferentegetClassLoader().getResourceAsStream("/myfile.txt")
.