关于 Java EE 中 ClassLoader 获取资源路径问题

2021-05-23 21:44:50 +08:00
 xiaopanzi

下面均假设资源文件均在main目录下面的resources里面:

在 Java SE 中,如果使用ClassLoader.getResource获取资源(包括ClassLoader.getResourceAsStream,下面不再重复),其路径不能以"/"开头。换言之,如果有个foo.txt的话,代码

getClass().getClassLoader().getResource("/foo.txt")

将返回null

但是我发现,如果在 Java EE 项目中,同样的情况,加不加"/"均能正常获取资源文件,这是为什么?


环境

1555 次点击
所在节点    Java
8 条回复
xiaopanzi
2021-05-23 22:16:21 +08:00
隐约找到了一个很可能的[解释]( https://stackoverflow.com/questions/2653322/getresourceasstream-not-loading-resource-in-webapp#comment5040719_2653353):大体的意思是 Tomcat 8 及之后,`WebAppClassloader` 能够同时处理带或者不带“/”的路径;而在 Tomcat 7 之前,仅能处理不带“/”的路径。显然,JDK 本身的`Classloader`还是只能处理不带“/”的路径。

但是对 Java EE 中这个`WebAppClassloader`相关类加载的东西还不是很懂,也没见到靠谱资料,是否有懂行的大佬推荐点相关资料?
israinbow
2021-05-23 22:25:09 +08:00
ide 的项目结构配置问题
xiaopanzi
2021-05-23 22:28:01 +08:00
@israinbow 能具体解释吗?我上面找到那个新版本 Tomcat 能够处理带“/”的路径的解释有问题吗?我也只是看到那个答案,不清楚具体情况?
israinbow
2021-05-23 23:18:37 +08:00
@xiaopanzi 以前在 idea 里遇见过一次, 印象里是 javaEE 的项目结构配置把路径映射了.tomcat 的解释是正确的, 使用 tomcat 会认定你的 java/src 目录是服务器里的某一个位置, 而不是 java 源代码的资源位置, tomcat7 和 8 的区别可以在更新日志里查到. 目前我个人对路径问题的解决方案: 转义符, 或首目录不加 / ,比如 "test/subtest/file.file". 参考文章: blog.csdn.net/aitangyong/article/details/36471881 以及
blog.csdn.net/mycomputerxiaomei/article/details/24472023
ikas
2021-05-23 23:20:04 +08:00
这个就是 tomcat 自己实现问题.你应该按照正常得写法,不带 /,具体你可以看 tomcat 源码,在 9 中,他内部实现: private String nameToPath(String name) {
if (name.startsWith("/")) {
return name;
}
StringBuilder path = new StringBuilder(
1 + name.length());
path.append('/');
path.append(name);
return path.toString();
}
xiaopanzi
2021-05-24 09:26:47 +08:00
@ikas 是的,后来我也看了 tomcat 的代码,定位到这个函数。多谢!
xiaopanzi
2021-05-24 09:32:06 +08:00
@israinbow 我觉得你的理解有部分误区。resources 里面的文件最后还是在 WEB-INF/classes 下面。终极原因是 tomcat 重写了 JDK 的 classloader 的代码,其中关键代码之一就是下面那位同学指出的 nameToPath 。换言之,你不加 /它反倒给你加上 /,用于拼接字符串放在“WEB-INF/classes”后面构成完整合法的路径。我说的“下面均假设资源文件均在 main 目录下面的 resources 里面”是标准的 Maven 工程结构。
israinbow
2021-05-24 12:14:26 +08:00
@xiaopanzi 的确, 我仔细看了一遍问题描述后觉得我的回答并不妥当, 但是楼下已经回答出要点了, 所以我也没有跟进( 对我的误导向你道歉

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/778724

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX