前几天在项目读取resources目录下的文件时碰到一个小坑,明明在本地是可以正常运行的,但是一发到测试环境就报错了,说找不到文件,报错信息是: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。

看了半天代码感觉没有问题,于是怀疑是打成项目jar包后和原项目存在差异导致的。于是我把的项目打成jar包,在本地直接调试jar,果然发现问题所在。下面我将以一个自己的测试项目api-test替代原来的公司项目来讲述一下排查过程。

一、项目代码

GetResourceTest:

public class GetResourceTest {
public InputStream getResource1() throws IOException {
File file = new DefaultResourceLoader().getResource("/template/qiankuan.ftl").getFile();
return Files.newInputStream(file.toPath());
} public InputStream getResource2() throws IOException {
ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
Resource[] resources = resolver.getResources("/template/qiankuan.ftl");
Resource resource = resources[0];
return resource.getInputStream();
}
}

TestController:

@RestController
@RequestMapping("/test")
public class TestController {
@GetMapping(value = "/getResource")
@ResponseBody
public void getResource() throws IOException {
GetResourceTest getResourceTest = new GetResourceTest();
getResourceTest.getResource1();
}
}

二、排查过程

1、首先使用Maven的install命令将项目打成jar包

命令执行成功后再target目录下就生成了jar包

2、在Termininal里cd到target目录下,然后执行下面的代码,9992可以替换成其他端口

java -jar -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=9992 api-test-1.0.0-SNAPSHOT.jar

执行成功如下

3、添加远程调试

依次点击菜单Run,点击Edit Configurations,点击+,点击Remote JVM Debug,端口后改成刚刚设置的9992。

4、请求接口

请求测试接口,9991是项目原来的端口

127.0.0.1:9991/test/getResource

5、请求结果

请求果然报错了,报错和之前测试环境的报错一摸一样。其实我们通过这个报错已经可以大致上看出问题了。。。

6、断点调试

在请求的入口打上断点开始断点调试

通过断点调试也可以看到这个文件地址在原来的地址/template/qiankuan.ftl 前拼接了jar:file:/D:/Project/test/fhey-test/api-test/target/api-test-1.0.0-SNAPSHOT.jar!/BOOT-INF/classes!成为了jar:file:/D:/Project/test/fhey-test/api-test/target/api-test-1.0.0-SNAPSHOT.jar!/BOOT-INF/classes!/template/qiankuan.ftl。

然后在后面一段代码中,resourceUrl.getProtocol()的返回结果是"jar"而不是"file", 被判定为不是文件然后抛出了一个FileNotFoundException异常。



三、解决方法

ResouceUtils.getFile()是专门用来加载非压缩和Jar包文件类型的资源,所以它根本不会去尝试加载Jar中的文件,要想加载Jar中的文件,只要用可以读取jar中文件的方式加载即可,比如 可以采用ClassPathResource这种以流的形式读取文件的方式或者PathMatchingResourcePatternResolver来读取文件。

ClassPathResource classPathResource = new ClassPathResource("/template/qiankuan.ftl" );
InputStream inputStream = classPathResource.getInputStream();

或者

ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
Resource[] resources = resolver.getResources("/template/qiankuan.ftl");
Resource resource = resources[0];
InputStream inputStream = resource.getInputStream();

解决Springboot项目打成jar包后获取resources目录下的文件失败的问题的更多相关文章

  1. SpringBoot项目打成jar包后上传文件到服务器 目录与jar包同级问题

    看标题好像很简单的样子,但是针对使用jar包发布SpringBoot项目就不一样了.当你使用tomcat发布项目的时候,上传文件存放会变得非常简单,因为你可以随意操作项目路径下的资源.但是当你使用Sp ...

  2. 解决springboot项目打成jar包部署到linux服务器后上传图片无法访问的问题

    前言:目前大三,自己也在学习和摸索的阶段.在和学校的同学一起做前后端分离项目的时候,我们发现将后端打包成jar,然后部署到服务器中通过java -jar xxx.jar运行项目以后,项目中存在文件上传 ...

  3. springboot项目打成jar包,启动指定外部的yml文件

    java -jar xxx.jar --spring.config.local=application.yml

  4. 【转载】JAVA SpringBoot 项目打成jar包供第三方引用自动配置(Spring发现)解决方案

    JAVA SpringBoot 项目打成jar包供第三方引用自动配置(Spring发现)解决方案 本文为转载,原文地址为:https://www.cnblogs.com/adversary/p/103 ...

  5. SpringBoot项目打成Jar包时运行

    使用java -jar ***.jar执行jar包的时候,会找jar包中的main()方法. 对于SpringBoot项目的Jar包,在META-INF目录下的MANIFEST.MF文件中,Main- ...

  6. spring boot 打jar包,获取resource路径下的文件

    前言:最近在spring boot项目静态类中获取resource路径下文件,在idea中启动都可以获取,但是打包后变成了jar包 就无法获取到. 我想到了两种方法,一种是根据http访问静态资源比如 ...

  7. JAVA SpringBoot 项目打成jar包供第三方引用自动配置(Spring发现)解决方案

    本项目测试环境 JDK: 1.8 SpringBoot: 2.1 需求描述 当我们想要利用SpringBoot封装一套组件并发布给第三方使用时,我们就不得不考虑我们的组件能否被使用者正确引入使用,此处 ...

  8. springboot项目打成jar包后台运行在linux上

    背景:springboot2为为主体搭建的项目,直接打成jar包,上传到linux上面 启动项目:java -jar xx.jar 这样很方便,但是不能关闭窗口,否则项目就停了 后台启动: nohup ...

  9. eclipse中,将springboot项目打成jar包

    1.右击项目,选择Run As - Maven clean 2.右击项目,选择Run As - Maven install 3.成功后 会在项目的target文件夹下生成jar包 4.将打包好的jar ...

  10. idea将springboot项目打成jar包

    1.首先,找到pom.xml,把下面的build块中的内容改成如下所示 <build> <plugins> <plugin> <groupId>org. ...

随机推荐

  1. [Python]PyCharm中出现unresolved reference的解决方法

    1 问题描述 2 解决方法 将你的目录添加sources root,即可解决此问题 (工程目录)>右键>Mark Directory As > Sources Root X 参考文献 ...

  2. [Windows]解决:windows连接远程桌面-出现身份验证错误,要求的函数不受支持( CredSSP加密数据库修正)[转载]

    文由 需要在本地Windows系统电脑通过远程桌面(mstsc)另一台Windows服务器,将其内的数据拷贝过来.但却发生了这样的异常 解决方案 step1 Win+R step2 打开注册表: gp ...

  3. 四月七号java基础学习

    1.数据类型分为基本数据类型以及引用数据类型 基本数据类型有整型.浮点型.字符型.布尔型 引用数据类型有类.数组以及接口 2.常量的声明需要用关键字final来标识 3.JAVA语言的变量名称由数字, ...

  4. Zabbix_sender基础命令浅析

    zabbix_sender是Zabbix监控系统中用于向Zabbix服务器发送数据的命令行工具.以下是zabbix_sender基础命令教学: 语法: zabbix_sender -z <ser ...

  5. React课堂笔记2

    一.JSX 1.1.什么是JSX JSX = JavaScript XML,这是React官方发明的一种JS语法(糖) 概念:JSX是 JavaScript XML(HTML)的缩写,表示在 JS 代 ...

  6. If选择语句的用法

    今天我们学习下If判断语句. 首先了解下它有几种用法: If单选择语句 If双选择语句 If多选择语句 我们一个一个用,每一个用法都给一个运用的过程演练一下. If单选择语句:我们很多需要判断一个东西 ...

  7. 求解 LCA の方法

    最近公共祖先(LCA) 最近公共祖先简称 LCA(Lowest Common Ancestor).两个节点的最近公共祖先,就是这两个点的公共祖先里面,离根最远的那个. -----oi wiki 举个例 ...

  8. ES6模块化之import的使用方式

    1.引入外部文件: <script src='文件路径' type='module'><!--PS:这个type="module" 必须要写,否则浏览器会报错-- ...

  9. 音视频八股文(10)-- mp4结构

    介绍 mp4⽂件格式⼜被称为MPEG-4 Part 14,出⾃MPEG-4标准第14部分 .它是⼀种多媒体格式容器,⼴泛⽤于包装视频和⾳频数据流.海报.字幕和元数据等.(顺便⼀提,⽬前流⾏的视频编码格 ...

  10. 2020-09-13:判断一个正整数是a的b次方,a和b是整数,并且大于等于2,如何求解?

    福哥答案2020-09-13: 首先确定b的范围,b的范围一定在[2,logN]里.然后遍历b,求a的范围,如果范围长度等于0,说明这个正整数是a的b次方.1.遍历b范围.二分法求a,a初始范围是[2 ...