Java加载资源文件时的路径问题的解决办法
加载资源文件比较常用的有两种:
一、用classloader,说到这里就不得不提一下classloader的分类,java内置的classloader主要有三种,
第一种是根类加载器(bootstrap class loader),用c++来编写,负责将一些关键的java类,如java.lang.object和其他一些运行时代码先加载进内存中。 所负责加载的包:bootstrp------>jre/lib/rt.jar
第二种是扩展类加载器(extclassloader),由java类编写,负责将jre中的一些类加载进内存中。所负责加载的包: extclassloader---------->jre/lib/ext/*.jar
第三种是应用类加载器(appclassloader)或者叫做系统类加载器,负责将classpath中的类加载到内存中。可以通过classloader.getsystemclassloader()来获取应用类加载器;
再来所说加类载器的继承,类加载器不是垂直继承的父子关系,而是一种组合关系,可以通过实例化类加载器时,将父类加载器的实例作为构造参数传到类加载器中。
关于类加载器的详细资料,可以自行搜索。
获取到应用类加载器之后,就是获取资源文件了,调用loader.getresource(path)可以加载相应路径下的资源文件,不能以‘/'开头,关于包内的资源可以把包当做普通的文件夹,以'/'分隔每个包。
如:url url2 = classloader.getsystemclassloader().getresource("demo/names.ser");是获取demo包内的names.ser序列化文件。
二、用需要加载的当前类的getresource方法来加载,其实这个方法也是调用的加载这个类的类加载器来获得资源文件的,只不过是获取的参数不同。
(1)要想获取class所在包内的文件可以用相对路径直接访问包内的资源;如:demo1.class.getresource("names.ser");获取的是demo1的class文件所在包内的资源
(2)要想获取包外的资源文件必须以‘/'开头,如url url = demo1.class.getresource("/demo/names.ser");获取的是demo包内的names.ser文件
其实第二种方式是对第一种方式的一个封装,都是用的classloader来加载的资源文件。为什么这么说呢?看一下class类的源码就知道:
public java.net.url getresource(string name) {
name = resolvename(name);
classloader cl = getclassloader0();
if (cl==null) {
// a system class.
return classloader.getsystemresource(name);
}
return cl.getresource(name);
}
private string resolvename(string name) {
if (name == null) {
return name;
}
if (!name.startswith("/")) {
class c = this;
while (c.isarray()) {
c = c.getcomponenttype();
}
string basename = c.getname();
int index = basename.lastindexof('.');
if (index != -1) {
name = basename.substring(0, index).replace('.', '/')
+"/"+name;
}
} else {
name = name.substring(1);
}
return name;
}
getresource根据传进来的name值(即相对路径或者绝对路径的形式),我们看到经过resolvename处理之后就调用了classloader c1进行了加载,classloader的加载路径的形式是不以‘/'开头的相对路径,那肯定是resolvename把路径转换了一把,再看看resolvename方法,首先判断是不是以‘/'开头,如果以‘/'开头,则为相对路径,否则就是绝对路径,注意else这个代码块,它将第一个字符去除掉了,确实去除掉之后就符合了classloader的加载路径,而if块中就根据把当前类的包路径截取,然后将.替换成了'/',并添加上那段相对路径,也形成了符合classloader的加载路径。
推荐阅读
-
Java加载资源文件时的路径问题的解决办法
-
详解java配置文件的路径问题
-
通过vue-router懒加载解决首次加载时资源过多导致的速度缓慢问题
-
IE8下载文件时无法调用迅雷怎么办?IE8浏览器无法用迅雷下载问题的解决办法介绍
-
解决vue-cli webpack打包后加载资源的路径问题
-
Java Web 前端资源文件的路径问题
-
解决加载WEB页面时,由于JS文件引用过多影响页面打开速度的问题
-
(终极解决办法)Android sdk manager就算配置了代理,也只有Tools单个文件(解决eclipse配置Android的sdk时只有Tools和extras的问题)
-
详解java配置文件的路径问题
-
00024.03 反射:使用类加载器来加载类路径下的资源文件(包含读取配置文件)