Class.getResource和getclassloaderr.getResource的区别分析

Java开发之路之关于Class.getResource和ClassLoader.getResource的路径问题
Java中取资源时,经常用到Class.getResource和ClassLoader.getResource。昨天老师讲解题目时候,问我们为什么你们都是在文件前家上&/&:
String path = Resources.class.getResource(&/a.txt&).getPath();
注:在Resources文件下创建了a.txt文件
我想我反正是试出来的,不使用&/&不行。为了正式解答心中的疑惑,我们正式来看看Resources路径问题。
1. Class.getResource(String path)
path不以&/'开头时,默认是从此类所在的包下取资源;
path以&/'开头时,则是从ClassPath根下获取;
System.out.println(&path:&+Resources.class.getResource(&/&));
System.out.println(&path:&+Resources.class.getResource(&&));
输出结果:
path:file:/home/xiaosi/Study/lectures/target/classes/
path:file:/home/xiaosi/Study/lectures/target/classes/com/qunar/lectures/
2. ClassLoder.getClassLoder.getResource(String path)
path不能以&/'开头时;
path是从ClassPath根下获取;
System.out.println(r.getClass().getClassLoader().getResource(&&));
System.out.println(r.getClass().getClassLoader().getResource(&/&));//null
输出结果:
file:/home/xiaosi/Study/lectures/target/classes/
(window.slotbydup=window.slotbydup || []).push({
id: '2467140',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467141',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467143',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467148',
container: s,
size: '1000,90',
display: 'inlay-fix'<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
您的访问请求被拒绝 403 Forbidden - ITeye技术社区
您的访问请求被拒绝
亲爱的会员,您的IP地址所在网段被ITeye拒绝服务,这可能是以下两种情况导致:
一、您所在的网段内有网络爬虫大量抓取ITeye网页,为保证其他人流畅的访问ITeye,该网段被ITeye拒绝
二、您通过某个代理服务器访问ITeye网站,该代理服务器被网络爬虫利用,大量抓取ITeye网页
请您点击按钮解除封锁&<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
您的访问请求被拒绝 403 Forbidden - ITeye技术社区
您的访问请求被拒绝
亲爱的会员,您的IP地址所在网段被ITeye拒绝服务,这可能是以下两种情况导致:
一、您所在的网段内有网络爬虫大量抓取ITeye网页,为保证其他人流畅的访问ITeye,该网段被ITeye拒绝
二、您通过某个代理服务器访问ITeye网站,该代理服务器被网络爬虫利用,大量抓取ITeye网页
请您点击按钮解除封锁&解决通过this.class.getResource()得到的URL中乱码的问题&.
ClassLoader的getResource方法使用了utf-8对路径信息进行了编码,当路径中存在中文和空格时,他会对这些字符进行转换,这样,得到的往往不是我们想要的真实路径,在此,调用了URLDecoder的decode方法进行解码,以便得到原始的中文及空格路径
例如:结果是file:/C:/Documents and
Settings/庄晓毅 &
Settings/Temp/temp0.jar!/db/dmozdata.mdb&&
而我们期望是 C:/Documents andsettigsd
sdfsdfsdf sdfsdf sdfsd 等等
这里我们只要在获取到的例如: String configPath =
this.getClass().getClassLoader().getResource("allowPath.xml").getFile();
把返回前decode下就可以了.
用utf-8编码.&
configPath&=&java.net.URLDecoder.decode(configPath,"utf-8");&&
已投稿到:
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。java核心(6)
Class#getResource方法的参数path可以与以'/'开头的绝对路径或是不以'/'开头的相对路径,当以'/'开头时,会从classpath路径下获取资源,当不以'/'开头时,则从该类所在的包下获取资源,xxx.class.getResource() 即xxx.class类所在包。而ClassLoader#getResource方法的参数却不能以'/'开头,其是从classpath下面获取资源。
来看看下面代码的结果
package com.jdk.
public class Resource {
public static void main(String[] args) throws Exception {
System.out.println(Resource.class.getResource(&&));
System.out.println(Resource.class.getResource(&/&));
System.out.println(Resource.class.getClassLoader().getResource(&&));
System.out.println(Resource.class.getClassLoader().getResource(&/&));
file:/D:/workspace/JDKCore/bin/com/jdk/resource/
file:/D:/workspace/JDKCore/bin/
file:/D:/workspace/JDKCore/bin/
可以看到Resource.class.getResource(&&)得到的路径classpath下Resource 类所在包,而Resource.class.getResource(&/&)为classpath根路径;而Resource.class.getClassLoader().getResource(&&)同样为classpath根路径,Resource.class.getClassLoader().getResource(&/&)则为空。 下面来看看Class#getResource方法的源码
public java.net.URL getResource(String name) {
name = resolveName(name);
ClassLoader cl = getClassLoader0();
if (cl==null) {
return ClassLoader.getSystemResource(name);
return cl.getResource(name);
从 cl.getResource(name)一行可以看出,Class#getResource方法最终还是调用了CalssLoader#getResource方法。再来看看name = resolveName(name)的实现,做了什么处理,其调用了Class类的resolveName方法
private String resolveName(String name) {
if (name == null) {
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('.', '/')
&#43;&/&&#43;
name = name.substring(1);
可以看出,resolveName方法的目的是当参数name以'/'开头就将'/'去除再返回,而当不以'/'开头则根据这个类对应的带包名全称变换成具体的路径名,如com.jdk.resource替换成com/jdk/resource。
现在应该明白最开始那个Resource 类中main方法的结果,实际上Class#getResource方法是去调CalssLoader#getResource的方法,只是在调用时会去判断是从相对路径还是绝对路径获取资源。不过api是有一点点坑Class#getResource以'/'开头与ClassLoader#getResource相同,再记住ClassLoader#getResource不能以'/'开头就行了。
有了前面这个Classr#getResource与ClassLoader#getResource的对比,Class#getResourceAsStream与ClassLoader#getResourceAsStream其实也就ok了。
Class#getResourceAsStream源码:
public InputStream getResourceAsStream(String name) {
name = resolveName(name);
ClassLoader cl = getClassLoader0();
if (cl==null) {
return ClassLoader.getSystemResourceAsStream(name);
return cl.getResourceAsStream(name);
ClassLoader#getResourceAsStream源码:
public InputStream getResourceAsStream(String name) {
URL url = getResource(name);
return url != null ? url.openStream() : null;
} catch (IOException e) {
return null;
所以,可以用下面三种方式得到资源
利用Class#getResourceAsStream方法根据绝对路径从classpath下面得到,参数path以'/'开头利用Class#getResourceAsStream方法根据类所处包的相对路径得到,参数path不能以'/'开头利用ClassLoader#getResourceAsStream方法根绝对路径从classpath下面得到,参数path不能以'/'开头
在com.jdk.resource目录下创建一个test.properties文件,可以用以下三种方式得到
package com.jdk.
public class Resource {
public static void main(String[] args) throws Exception {
System.out.println(Resource.class.getResourceAsStream(&test.properties&));
System.out.println(Resource.class.getResourceAsStream(&/com/jdk/resource/test.properties&));
System.out.println(Resource.class.getClassLoader().getResourceAsStream(&com/jdk/resource/test.properties&));
java.io.BufferedInputStream@659e0bfd
java.io.BufferedInputStream@2a139a55
java.io.BufferedInputStream@15db9742
这对查看,Spring Resource 接口的实现ClassPathResource类getInputStream方法有一定帮助
public InputStream getInputStream() throws IOException {
InputStream is;
if (this.clazz != null) {
is = this.clazz.getResourceAsStream(this.path);
else if (this.classLoader != null) {
is = this.classLoader.getResourceAsStream(this.path);
is = ClassLoader.getSystemResourceAsStream(this.path);
if (is == null) {
throw new FileNotFoundException(getDescription() &#43; & cannot be opened because it does not exist&);
return is;
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:947次
排名:千里之外
转载:15篇

我要回帖

更多关于 class.getclassloader 的文章

 

随机推荐