在开发java程序的过程中我们经常要做的一件事就是获取资源那么什么是资源呢?说白了在计算机里那就是一堆数据只是这堆数据对我们的java程序有多种表现形式一般来说有FileURLInputStream等等而单就文件这一项就有很多种配置文件java类文件jps文件图片cssjs文件等等面对这林林总总的资源我们在设计一个读取资源的接口时就需要针对不同形式的资源提供方法这样就导致我们的接口还是与实际的资源形式绑定在一起未能完全的抽象另外在java程序中资源的存放位置也是各异的有的存放在classpath中有的存放在文件系统中有的存放在web应用中而对于不同位置的资源java程序获取这些资源的方法各有不同
A获取classpath中的资源
Java代码
URL url = thisgetClass()getResource(resource_name);
URL url = thisgetClass()getClassLoader()getResource(resource_name);
URL url = ThreadcurrentThread()getContextClassLoader()getResource(resource_name);
甜性涩爱下载 ?id=
那么在jdk中为什么又提供了三种方式来获取classpath下的资源呢?这其中是有些来头的
第一行代码中是利用Class类的实例来获取第二行代码是使用加载当前类的classloader来获取看下jdk中的源代码会发现class类的实例最后还是委托加载他的classloader来获取资源的
Java代码
public URL getResource(String name) {
name = resolveName(name);
ClassLoader cl = getClassLoader();
if (cl==null) {
// A system class
return ClassLoadergetSystemResource(name);
}
return clgetResource(name);
}
从上面的代码中可以看出对于资源的加载并没有像类加载所采用的双亲委托机制而是当前类的classloader不为null的情况下先从当前类的classloader中加载资源而只有当前类的classloader为null的时候才从system classloader中去加载资源这样可以方便我们自定义配置类覆盖一些默认配置当然jse应用中如果没有特别定制classloader时我们自己写的类都是被system classloader加载的到底利用class去获取资源和利用classloader去获取资源有什么区别呢?区别就在 resolveName(name)这个方法中两种方式对于资源名称的表示方式不同下面是一个简单的包结构/表示类路径的根
/
|test
|Testclass
|testtxt
|testtxt
Java代码
// 获取与当前类在同一个包下的资源
URL url = thisgetClass()getResource(testtxt);
// 获取test包下的资源需加/
URL url = thisgetClass()getResource(/com/cn/test/testtxt);
// 获取类路径根下的资源
URL url = thisgetClass()getClassLoader()getResource(testtxt);
// 获取包test包下的资源
URL url = thisgetClass()getResource(com/cn/test/testtxt);
而第三利用当前线程的contextClassLoader来获取资源的解释可以参考我的另一篇
B获取文件系统中的资源
Java代码
// 获得File对象
File file = new File(testtxt);
// 获得File对象的字节流
InputStream in = new FileInputStream(file);
值得注意的是在File的构造函数File(String name) 中的name参数可以是相对路径和绝对路径相对路径是相对于SystemgetProperties(userdir)的
C获取web应用中的资源
Java代码
servletContextgetResourceAsStream(resource_name);
resource_names为相对于webroot的路径表示例如获取webxmlresource_name表示为/WEBINF/webxml
面对上面介绍的各种资源表现形式和存放位置难道java中就没有提供一个统一处理方式吗?有URL
从名称上来看 URL(Uniform Resource Locator) 统一资源定位器看起来很好很强大但很多时候使用它并不能定位到我们需要的资源
首先它jdk中体统的URL能访问的协议非常有限(当然可以进行扩展不过很麻烦)常用的有httpfileftp等等并没有提供对classpath和servletContext中的资源的获取方法
另外它没有提供判断资源是否存在的方法每次只有等我们真正去获取资源的时候抛出异常才能知道资源无法获取
其次URL这个类的职责未划分清楚既用来表示资源有用来获取其资源