关于 Java EE 中 ClassLoader 获取资源路径问题 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
xiaopanzi
V2EX    Java

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

  •  
  •   xiaopanzi 2021 年 5 月 23 日 1992 次点击
    这是一个创建于 1797 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

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

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

    将返回null

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


    环境

    • OpenJDK 11
    • Tomcat 9
    • Servlet 4.0
    8 条回复    2021-05-24 12:14:26 +08:00
    xiaopanzi
        1
    xiaopanzi  
    OP
       2021 年 5 月 23 日
    隐约找到了一个很可能的[解释]( https://stackoverflow.com/questions/2653322/getresourceasstream-not-loading-resource-in-webapp#comment5040719_2653353):大体的意思是 Tomcat 8 及之后,`WebAppClassloader` 能够同时处理带或者不带“/”的路径;而在 Tomcat 7 之前,仅能处理不带“/”的路径。显然,JDK 本身的`Classloader`还是只能处理不带“/”的路径。

    但是对 Java EE 中这个`WebAppClassloader`相关类加载的东西还不是很懂,也没见到靠谱资料,是否有懂行的大佬推荐点相关资料?
    israinbow
        2
    israinbow  
       2021 年 5 月 23 日
    ide 的项目结构配置问题
    xiaopanzi
        3
    xiaopanzi  
    OP
       2021 年 5 月 23 日
    @israinbow 能具体解释吗?我上面找到那个新版本 Tomcat 能够处理带“/”的路径的解释有问题吗?我也只是看到那个答案,不清楚具体情况?
    israinbow
        4
    israinbow  
       2021 年 5 月 23 日
    @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
        5
    ikas  
       2021 年 5 月 23 日
    这个就是 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
        6
    xiaopanzi  
    OP
       2021 年 5 月 24 日
    @ikas 是的,后来我也看了 tomcat 的代码,定位到这个函数。多谢!
    xiaopanzi
        7
    xiaopanzi  
    OP
       2021 年 5 月 24 日
    @israinbow 我觉得你的理解有部分误区。resources 里面的文件最后还是在 WEB-INF/classes 下面。终极原因是 tomcat 重写了 JDK 的 classloader 的代码,其中关键代码之一就是下面那位同学指出的 nameToPath 。换言之,你不加 /它反倒给你加上 /,用于拼接字符串放在“WEB-INF/classes”后面构成完整合法的路径。我说的“下面均假设资源文件均在 main 目录下面的 resources 里面”是标准的 Maven 工程结构。
    israinbow
        8
    israinbow  
       2021 年 5 月 24 日
    @xiaopanzi 的确, 我仔细看了一遍问题描述后觉得我的回答并不妥当, 但是楼下已经回答出要点了, 所以我也没有跟进( 对我的误导向你道歉
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     929 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 36ms UTC 22:34 PVG 06:34 LAX 15:34 JFK 18:34
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86