清晨好,起得真早啊...
登录注册
2019-12-09 10:35:14

SpringBoot项目打包成jar后读取文件的大坑,使用ClassPathResource获取classpath下文件失败

我在读取邮件模板的时候,本地测试使用ClassPathResource都可以正常读取,但打包成jar包传到服务器上就无法获取了,报错信息是:class path resource [xxxx] cannot be resolved to absolute file path because it does not reside in the file system: jar:file:xxxx.jar!/BOOT-INF/classes!xxxx,话不多说,先看正确的获取方法:使用PathMatchingResourcePatternResolver。

String txt = "";
ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
Resource[] resources = resolver.getResources("templates/layout/email.html");
Resource resource = resources[0];
//获得文件流,因为在jar文件中,不能直接通过文件资源路径拿到文件,但是可以在jar包中拿到文件流
InputStream stream = resource.getInputStream();
StringBuilder buffer = new StringBuilder();
byte[] bytes = new byte[1024];
try {
    for (int n; (n = stream.read(bytes)) != -1; ) {
        buffer.append(new String(bytes, 0, n));
    }
} catch (IOException e) {
    e.printStackTrace();
}
txt = buffer.toString();

然后,想知道更多的咱们就继续看看是怎么回事,如果只是为了解决问题,那就可以忽略下面的内容了。

为了老夫好奇的心,我们继续探索下去,到底是怎么回事?我们先看看之前的代码:

String txt = "";
Resource resource = new ClassPathResource("templates/layout/email.html");
txt = fileUtil.readfile(resource.getFile().getPath());

其实这是一个jar包发布的大坑,相信很多小伙伴遇到了读取文件的问题,其实使用getFile()的时候的坑,为了弄明白到底是咋回事,我进行了跟踪,结果返回的是一个Jar协议地址:jar:file:/xxx/xx.jar!/xxxx。
 

然后继续跟踪到org.springframework.util.ResourceUtils#getFile(java.net.URL, java.lang.String)中,有如下的判断:

public static File getFile(URL resourceUrl, String description) throws FileNotFoundException {
    Assert.notNull(resourceUrl, "Resource URL must not be null");
    if (!"file".equals(resourceUrl.getProtocol())) {
        throw new FileNotFoundException(description + " cannot be resolved to absolute file path because it does not reside in the file system: " + resourceUrl);
    } else {
        try {
            return new File(toURI(resourceUrl).getSchemeSpecificPart());
        } catch (URISyntaxException var3) {
            return new File(resourceUrl.getFile());
        }
    }
}

因为resourceUrl.getProtocol()不是file,而是 jar,这样就抛出了一个FileNotFoundException异常。

ResouceUtils.getFile()是专门用来加载非压缩和Jar包文件类型的资源,所以它根本不会去尝试加载Jar中的文件,要想加载Jar中的文件,只要用可以读取jar中文件的方式加载即可,比如 xx.class.getClassLoader().getResouceAsStream()这种以流的形式读取文件的方式,所以使用读取文件流就可以拿到了。

评论与留言

以下内容均由网友提交发布,版权与真实性无法查证,请自行辨别。
那不就是可以用ClassPathResource对象的getInputStream方法吗
  • 2020-09-12 22:49:35
  • Wuxi, Jiangsu, China
  • 回复
本站有缓存策略,时间约2小时后能看到您的评论。本站使用自动审核机制,如果您的内容包含广告/谩骂/恐怖/暴力/涉政等不和谐内容将无法展示!
微信订阅号
扫码关注「任霏博客」微信订阅号
反馈与讨论
感谢您的关注与反馈
如果您发现了BUG、安全漏洞、或者希望讨论技术内容,请点击下方链接对我进行反馈。
feedback
最新留言