class.getResource与classloader.getResource

前言

之前偶然看到一篇别人写的文章 https://www.cnblogs.com/drwong/p/5389631.html .对于怎么找到classpath下的资源,比如图片呀,视频呀什么的..勾起了我的一点好奇心.

现在大家项目一般都是springboot的.那加载资源还是比较简单的..比如ClassPathResource呀..PathMatchingResourcePatternResolver呀(没有仔细确认,但是我印象中mybatis整合spring-boot的时候是用这个类去加载xml配置的)等等.

但是原生的java方法.或者比如以前大学时代做gui的时候.没有spring.加载个图片可能用的最多的就是class.getResource或者classloader.getResource了.那么到底该用哪个方法? 资源开头是不是要加斜杠 / 呢? 这里我记录一下我的想法.

 

class.getResource

基本操作大概就是下面这样

 1 package test;
 2 
 3 public class ClassLoaderTest2 {
 4 
 5     public static void main(String[] args) throws ClassNotFoundException {
 6         ClassLoaderTest2.class.getResource("/"); // name = "" subString(1)
 7         ClassLoaderTest2.class.getResource(""); // name = "test/"  .会被替换成/
 8         // name = resolveName(name); ClassLoader.getResource
 9     }
10 }

class.getResource最终是会掉classLoader.getResource方法的.但是会对你传入的字符串进行一些处理

 

 在resolveName这一步中.

 

 

如果你是传入的是/开头的字符串.那返回的name就是去掉/的内容.在我的例子里返回就是"",即空字符串.

如果你传入的不是/开头的字符串.那他会把你的className中的.全部替换成/  比如我的class是test.ClassLoaderTest2 那就会变成 test/  所以我传入的""就变成了 "test/"

可以参考我代码中的注释.

 

classloader.getResource

因为class.getResource最后也是调用了classloader.getResurce.所以最终怎么找资源还是得看你的classloader是怎么写的.是哪个classloader.

所以就想那篇文章中写的.在main运行程序与在tomcat里运行程序会有不同的现象.

因为在tomcat中运行的时候classloader是webappClassLoader.

 

 

他会对你传入的name做处理.不管你是/开头还是不是/开头.都会去掉这个/然后拼接上/WEB-INF/classes/

 

 

 

所以在tomcat下你写/开头还是不写/开头都是一样的.都是相对/WEB-INF/classes下的路径.

 

但是如果不是tomcat的classloader,比如在main里运行.那classloader是AppClassLoader.里面最终会调用sun.misc.URLClassPath.findResource 没有源码..追不下去了.

测试结果是写相对路径(没有/)的时候是相对于你的classes的例如/D:/work/idea/ws/test/target/classes/

如果写绝对路径/开头.会直接找不到资源.

 

小结

小结一下.如果你是main里运行的程序.

如果是class.getResource.那就写/开头然后跟上你的classes下的相对路径地址

如果你是classloader.getResource.那就不要写/开头.然后跟上你的classes下的相对路径地址

 

posted @ 2020-01-30 13:15  abcwt112  阅读(234)  评论(0编辑  收藏  举报