ResouceUtils.getFile()取不到Jar中资源文件源码小结
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中资源文件源码小结的更多相关文章
- eclipse中导入jar文件的源码
有时候想看看一个jar包的源码是怎么写的,想按Ctrl+鼠标左键点击来自动导航这时候就需要先把源码给导入到eclipse中,步骤如下:首先准备jar包和源文件包比如:
- 各个版本spring的jar包以及源码下载地址
各个版本spring的jar包以及源码下载地址,目前最高版本到spring4.1.2,留存备用: http://maven.springframework.org/release/org/spring ...
- Eclipse开发环境debug模式调试断点从jar跳到源码
Eclipse开发环境debug模式调试断点从jar跳到源码 说明:本案例使用jsch-0.1.54.jar和源码做test,项目分成两个,一个是jsch的源码,另一个是测试案例 一.下载JSch.的 ...
- Eclipse里面的Maven项目如果下载依赖的jar包的源码
Window---------Properties---------------Maven--------------勾选Download Artifact Sources和Download Arti ...
- Eclipse中调试Jar包的源码(调试Struts2源码)
首先在Eclipse中创建一个新的项目,加入运行Struts2所需要的JAR文件,并将它们加到项目的CLASSPATH中(在Lisbs中右击 build path 如下图: ),成功后的界面如图 1- ...
- eclipse调试第三方jar包需要源码的问题
很多时候测试自己的jar包功能时,需要有一个测试工程导入该jar包,但是一般在调试的时候,需要跟进去看看步骤和逻辑是否正确,这个时候就需要在jar包的源码中下断点.最近刚好自己也会经常这样做,也遇到了 ...
- 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 ...
- IDEA 全局搜索 Jar 包中源码内容
引言 项目开发过程中,经常遇到需要在依赖的 Jar 包查看源码,查找类方法和属性,介绍两种在 IDEA 中搜索 Jar 包内容的方式 方式一:双击 SHIFT 快捷键 输入需要查询的类名或方法名 方式 ...
- htmlunit抓取js执行后的网页源码
上次我不是写了一个自动抓取博客访问量吗 (点击打开链接) 可是昨天晚上我又运行的时候,发现不能用了.. 运行了几次 发现使用URLConnection 得到的网页源码和浏览器直接查看的不同. URLC ...
随机推荐
- Ubuntu18.04的网络配置
网卡与DNS配置 1)打开命令窗口(右键单机桌面选择Open Terminal或者用快捷键Ctrl+Alt+T打开终端),输入ip a查看自己的网卡编号 2)输入命令sudo vim /etc/net ...
- typeScript入门基础 (2): 数据 类型, 函数定义
1. number , boolean, string, null, undefind 枚举, any, array数组, 元祖, 2...枚举,需要的注意点, 下一个图,就是为什么yello ...
- java正则常用记录
1. java中 字符串的某个字母是否有某个指定字符N : for(int i=0;i<temp.length();i++){ if( temp.get(i).substring(0,1) ...
- 《剑指offer》第六十题(n个骰子的点数)
// 面试题60:n个骰子的点数 // 题目:把n个骰子扔在地上,所有骰子朝上一面的点数之和为s.输入n,打印出s // 的所有可能的值出现的概率. #include <iostream> ...
- 配置java环境jdk
最近尝试改公司的项目中的一个后台管理系统,前后台都让我一个做,所以要配置一下java环境: 1. 按装jdk 1.6//2. 安装eclipse3. 安装maven4. 安装eclispe的maven ...
- js时间戳如何转时间
js时间戳如何转时间 一.总结 一句话总结:Date对象分别获取年now.getFullYear()月now.getMonth()+1日now.getDate()即可 Date对象分别获取年now.g ...
- oracle.exe 内存占用过大
现象: 明明各个schema 占用的磁盘空间都不大. oracle.exe 却占用了差不多 3G 的内存. 解决: 查了google,各种英文关键字没有找到原因. 最后,中文检索到了. https:/ ...
- RepBaseRepeatMaskerEdition下载 | RepeatMasker
开源的生物信息世界居然有这么个需要注册才能下载的工具,开源世界不是怎么方便怎么来吗? 这个注册真的麻烦,这里上传了一个可以使用的版本. RepBaseRepeatMaskerEdition-20170 ...
- Centos6.5 升级Openssl + Openssh
xu言: 平时很懒,都不想写blog.今天(2018.05.15)开始尝试每天写一篇吧,看我自己能坚持多久! 准备工作: 为了防止在操作过程中导致ssh远程中断,首先安装一个telnet-server ...
- 20170923xlVBA_UpdateClientDetailSQL_Dictionary
Sub UpdateClientDetailWGQ() Dim Wb As Workbook Dim Sht As Worksheet Dim Rng As Range Dim Arr As Vari ...