Spring提供了一个工具类可以加载classpath下的文件,一般情况下无任何问题,但是当它作为公共的jar包中的工具来加载jar包中的文件时则报出找不到文件的错误.

点开看了一下这个工具类ResouceUtils.getFile()方法的源码:

public static File getFile(String resourceLocation) throws FileNotFoundException {
Assert.notNull(resourceLocation, "Resource location must not be null");
if (resourceLocation.startsWith(CLASSPATH_URL_PREFIX)) {
String path = resourceLocation.substring(CLASSPATH_URL_PREFIX.length());
String description = "class path resource [" + path + "]";
ClassLoader cl = ClassUtils.getDefaultClassLoader();
URL url = (cl != null ? cl.getResource(path) : ClassLoader.getSystemResource(path));
if (url == null) {
throw new FileNotFoundException(description +
" cannot be resolved to absolute file path because it does not exist");
}
return getFile(url, description);
}
try {
// try URL
return getFile(new URL(resourceLocation));
}
catch (MalformedURLException ex) {
// no URL -> treat as file path
return new File(resourceLocation);
}
}

看了一下代码结构简单逻辑清晰,可能有问题的也就是上图标红的2处.这里我第一印象是类加载器加载资源的时候没加载到.Debug了一下cl.getResource(path)用的类加载器是

WebAppClassLoader,想看一下内部实现,但是到这里就跟不进去了,然后百度了一下发现这个是Jetty实现的自己的ClassLoader,截取部分关键的加载源码:

public void addJars(Resource lib)  {
if (lib.exists() && lib.isDirectory())
{
String[] files=lib.list();
for (int f=0;files!=null && f<files.length;f++) {
try {
Resource fn=lib.addPath(files[f]);
String fnlc=fn.getName().toLowerCase();
if (fnlc.endsWith(".jar") || fnlc.endsWith(".zip")) {
String jar=fn.toString();
jar=StringUtil.replace(jar, ",", "%2C");
jar=StringUtil.replace(jar, ";", "%3B");
addClassPath(jar);
}
} catch (Exception ex) {
Log.warn(Log.EXCEPTION,ex);
}
}
}
}

上面这块是把jar和zip的path加到类加载器路径中的部分源码.继续debug得到

URL url = (cl != null ? cl.getResource(path) : ClassLoader.getSystemResource(path));

上面的url结果:

实际上取到了要加载的文件路径,由于在jar包中,协议字段被标识为jar.到这里看来并非类加载器导致的加载文件失败.那只好继续debug往下看getFile()的源码:

public static File getFile(URL resourceUrl, String description) throws FileNotFoundException {
Assert.notNull(resourceUrl, "Resource URL must not be null");
if (!URL_PROTOCOL_FILE.equals(resourceUrl.getProtocol())) { //URL_PROTOCOL_FILE="file"
throw new FileNotFoundException(
description + " cannot be resolved to absolute file path " +
"because it does not reside in the file system: " + resourceUrl);
}
try {
return new File(toURI(resourceUrl).getSchemeSpecificPart());
}
catch (URISyntaxException ex) {
// Fallback for URLs that are not valid URIs (should hardly ever happen).
return new File(resourceUrl.getFile());
}
}

看到这里有点无语了,上面红色字体的部分实际判断资源路径的协议是否为file,由于在jar包中,协议是jar,故到此处直接抛出文件未找到的异常,

顿时觉得自己好傻,debug这么久,又理了一遍类加载的过程,其实问题是很简单的一个问题,ResouceUtils.getFile()是专门用来加载非压缩和Jar包文件类型的资源,所以它根本不会

去尝试加载Jar中的文件,要想加载Jar中的文件,只要用可以读取jar中文件的方式加载即可,比如 xx.class.getClassLoader().getResouceAsStream()这种以流的形式读取文件的方式.

ResouceUtils.getFile()取不到Jar中资源文件源码小结的更多相关文章

  1. eclipse中导入jar文件的源码

    有时候想看看一个jar包的源码是怎么写的,想按Ctrl+鼠标左键点击来自动导航这时候就需要先把源码给导入到eclipse中,步骤如下:首先准备jar包和源文件包比如:

  2. 各个版本spring的jar包以及源码下载地址

    各个版本spring的jar包以及源码下载地址,目前最高版本到spring4.1.2,留存备用: http://maven.springframework.org/release/org/spring ...

  3. Eclipse开发环境debug模式调试断点从jar跳到源码

    Eclipse开发环境debug模式调试断点从jar跳到源码 说明:本案例使用jsch-0.1.54.jar和源码做test,项目分成两个,一个是jsch的源码,另一个是测试案例 一.下载JSch.的 ...

  4. Eclipse里面的Maven项目如果下载依赖的jar包的源码

    Window---------Properties---------------Maven--------------勾选Download Artifact Sources和Download Arti ...

  5. Eclipse中调试Jar包的源码(调试Struts2源码)

    首先在Eclipse中创建一个新的项目,加入运行Struts2所需要的JAR文件,并将它们加到项目的CLASSPATH中(在Lisbs中右击 build path 如下图: ),成功后的界面如图 1- ...

  6. eclipse调试第三方jar包需要源码的问题

    很多时候测试自己的jar包功能时,需要有一个测试工程导入该jar包,但是一般在调试的时候,需要跟进去看看步骤和逻辑是否正确,这个时候就需要在jar包的源码中下断点.最近刚好自己也会经常这样做,也遇到了 ...

  7. MyEclipse中android 项目如何解决第三方jar无法关联源码的问题( The JAR of this class file belongs to container 'Android Private Libraries' which does not allow modifications to source attachments on its entries.)

    若我们要为第三方jar(android-support-v4.jar)关联源码通常的做法是 右键项目 单击菜单Properties 单击菜单 Java Build Path 单击 Libraries ...

  8. IDEA 全局搜索 Jar 包中源码内容

    引言 项目开发过程中,经常遇到需要在依赖的 Jar 包查看源码,查找类方法和属性,介绍两种在 IDEA 中搜索 Jar 包内容的方式 方式一:双击 SHIFT 快捷键 输入需要查询的类名或方法名 方式 ...

  9. htmlunit抓取js执行后的网页源码

    上次我不是写了一个自动抓取博客访问量吗 (点击打开链接) 可是昨天晚上我又运行的时候,发现不能用了.. 运行了几次 发现使用URLConnection 得到的网页源码和浏览器直接查看的不同. URLC ...

随机推荐

  1. MAC office2016 安装及激活

    Office 下载地址: http://www.xitongtiandi.net/soft_yy/4285.html 破解补丁下载地址: https://bbs.feng.com/tencentdow ...

  2. Python 模块(module)

    模块(module)也是为了同样的目的.在Python中,一个.py文件就构成一个模块.通过模块,你可以调用其它文件中的程序. first.py def laugh(): print "Ha ...

  3. ASP.net 网站开发知识点总结

    一.常用技术概括及介绍 1. SQL server:处理数据库的设计 2. asp.net  3. html            :前端网页 4. css :网页的布局设计 5. JavaScrip ...

  4. Cordova插件:InAppBrowser

    版权声明:本文为博主原创文章,转载请注明出处 一.应用场景 我们在做cordova app开发的时候,可能会经常遇到这种需求.比如在你的app中,你想打开一个URL,但是又不想跳转到系统的浏览器去打开 ...

  5. 学习笔记14—Python error集

    1.Can't broadcast input array from shape (3,1) into shape (3,) resolution:    V[k:m,k] = v; v has sh ...

  6. ubuntu配置chrome git

    安装chrome (也可以直接从官网下载deb包安装) sudo wget http://www.linuxidc.com/files/repo/google-chrome.list -P /etc/ ...

  7. ubuntu18重装后 基本需求安装

    以下为本人重装ubuntu18后的基本需求安装过程 1 apt-fast sudo add-apt-repository ppa:apt-fast/stable sudo apt-get update ...

  8. echart 圆滑初始化化

    圆滑:主题下载对应主题js引入后注入对应名称参数方可使用主题 初始化:tab点击的时候初始化图表涉及到tab切换到的需要延迟加载否则默认宽度为100px 1.创建macarons.js文件 2.页面添 ...

  9. requests库使用:通过cookie跳过验证码登录,并用Session跨请求保持cookie

    拿我平时测试的一个系统为例,从UI层面来说必须先登录才可以进行后续操作,但是我在测试接口文档提供的接口时,发现并不需要登录,每个接口只要传参就可以正常返回.原因是我们这边专门弄了一个接口包来统一管理常 ...

  10. (转)C# 的 String.CompareTo、 Equals和==的比较

    String.CompareTo 语法 public int CompareTo(    string strB) 返回值 小于 0,实例小于参数 strB: 0,实例等于参数 strB: 大于 0, ...