getResourceAsStream() 总是返回 null

52

我在一个Java Web应用程序中有以下结构:

TheProject
  -- [Web Pages]
  -- -- [WEB-INF]
  -- -- -- abc.txt
  -- -- index.jsp
  -- [Source Packages]
  -- -- [wservices]
  -- -- -- WS.java

WS.java中,我在Web方法中使用以下代码:

InputStream fstream = this.getClass().getResourceAsStream("abc.txt");

但它总是返回 null。我需要从那个文件中读取内容,并且我了解到如果将文件放在 WEB-INF 中,则可以使用 getResourceAsStream 访问它们,但该方法始终返回 null

有什么想法我可能做错了什么吗?

顺便说一句,奇怪的是这曾经起作用,但在我对项目进行了 Clean and Build 后,它突然停止工作了 :/

7个回答

40
据我所知,文件必须放在包含'this'类的文件夹中,也就是说不能放在WEB-INF/classes目录下,而是更深的嵌套目录中(除非你使用默认包):

据我所知,该文件必须直接放置在包含'this'类的文件夹中,即不能放在WEB-INF/classes目录下,而是需要更深层次的嵌套(除非您使用默认包):

net/domain/pkg1/MyClass.java  
net/domain/pkg1/abc.txt

将文件放入Java源代码中应该可行,编译器会将该文件与类文件一起复制。


+1 干得好,老铁。我把文件移到了 wservices 目录下,现在它可以工作了。 - Andreas Grech
4
如果你正在使用Eclipse,你还需要按下‘F5’键(刷新),这样你的'abc.txt'才会出现在包资源管理器中,否则getResource()始终返回null。 - Chris Huang-Leaver
我发现在Eclipse/maven中,单元测试对文件位置更加宽容,但当打包和部署后,文件只有在我按照此答案的建议移动到与类所在位置匹配时才能正常工作。 - Aaron Roller

31
调用 Class#getResourceAsStream(String) 会委托给类加载器,在类路径中搜索资源。换句话说,你当前的代码不会起作用,你应该将 abc.txt 放在 WEB-INF/classes 中,或者如果打包在 JAR 文件中,则将其放在 WEB-INF/lib 中。

或者 使用 ServletContext.getResourceAsStream(String),它允许 Servlet 容器从任何位置向 Servlet 提供资源,而无需使用类加载器。因此,从 Servlet 中使用此方法:

this.getServletContext().getResourceAsStream("/WEB-INF/abc.txt") ;
但是我能否从我的 Web Service 中调用 getServletContext 的方法呢?如果您正在使用 JAX-WS,则可以注入一个 WebServiceContext:
@Resource
private WebServiceContext wsContext;

然后从中获取ServletContext

ServletContext sContext= wsContext.getMessageContext()
                             .get(MessageContext.SERVLET_CONTEXT));

2
但是我能否从我的Web服务中调用getServletContext方法呢? - Andreas Grech

30

不是

InputStream fstream = this.getClass().getResourceAsStream("abc.txt"); 

使用

InputStream fstream = this.getClass().getClassLoader().getResourceAsStream("abc.txt");

这样做将从根目录而不是当前调用类的路径查看。


3
哥们,我跟空指针打了三个小时,结果看到你的评论就秒懂了,谢啦! - Shell Scott

11

我认为这样可以从“任何地方”获取文件(包括服务器位置),而且您不需要关心放置文件的位置。

必须关注这些事情通常是一个不好的习惯。

Thread.currentThread().getContextClassLoader().getResourceAsStream("abc.properties");

1
非常高兴我找到了这个答案。非常感谢!其他方法都没用,但这个确实有效。 - 90abyss
我和前面的评论者一样:没有其他方法有效!但是你的解决方案真是太好了。第一次尝试,没有问题。非常感谢! - jaylawl

5

我不确定这是否适用于JAX-WS,但对于JAX-RS,我能够通过注入ServletContext并调用它的getResourceAsStream()方法来访问文件:

@Context ServletContext servletContext;
...
InputStream is = servletContext.getResourceAsStream("/WEB-INF/test_model.js");

请注意,在GlassFish 3.1中,路径必须是绝对的,即以斜线开头。更多信息请参见:如何在jax-rs中使用属性文件?


1

当我从Websphere 8.5切换到WebSphere Liberty时,遇到了同样的问题。

我使用了FileInputStream而不是getResourceAsStream(),因为由于某种原因,WebSphere Liberty无法找到WEB-INF文件夹中的文件。

脚本如下:

FileInputStream fis = new FileInputStream(getServletContext().getRealPath("/") 
                        + "\WEBINF\properties\myProperties.properties")

注意:

我仅在开发过程中使用了此脚本。


1

我曾经遇到类似的问题,并且花了很长时间寻找解决方案: 看来字符串参数是大小写敏感的。所以如果您的文件名是abc.TXT,但是您搜索的是abc.txt,eclipse会找到它 - 可执行的JAR文件不会。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接