首页 > 其他分享 >解决Springboot项目打成jar包后获取resources目录下的文件失败的问题

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

时间:2023-07-03 20:11:20浏览次数:28  
标签:包后 Springboot jar 报错 file test ftl resources

前几天在项目读取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,报错,file,test,ftl,resources
From: https://www.cnblogs.com/fhey/p/17523887.html

相关文章

  • SpringBoot 服务接口限流
    前言在开发高并发系统时有三把利器用来保护系统:缓存、降级和限流。限流可以认为服务降级的一种,限流通过限制请求的流量以达到保护系统的目的。一般来说,系统的吞吐量是可以计算出一个阈值的,为了保证系统的稳定运行,一旦达到这个阈值,就需要限制流量并采取一些措施以完成限制流量的......
  • SpringBoot项目从0到1配置logback日志打印
    大家好!我是sum墨,一个一线的底层码农,平时喜欢研究和思考一些技术相关的问题并整理成文,限于本人水平,如果文章和代码有表述不当之处,还请不吝赐教。以下是正文!一、写文背景我们在写后端项目的时候,日志打印是必需的。支持SpringBoot项目的日志框架一般有log4j、logback,这二者各有优......
  • springboot中SPI的实现
    在SpringBoot中,可以使用Java的SPI机制来实现SPI。首先,定义一个接口,例如:publicinterfaceMyService{voiddoSomething();}然后,在该接口的实现类中使用Java的SPI注解,例如:publicclassMyServiceImplimplementsMyService{@OverridepublicvoiddoSomethin......
  • springBoot面经
    对springboot的了解,SpringBoot自动装配原理答:自动装配就是自动把第三方组件的Bean转载到IOC容器里面,不需要去手动配置。在springboot应用里只需要在启动类上加上@SpringBootApplication注解,就可以实现自动装配。这个复合注解中主要实现自动装配的注解是@EnableAutoConfiguration......
  • Task Execution and Scheduling In SpringBoot
    开天辟地TaskExecutionandSchedulingIntheabsenceofanExecutorbeaninthecontext,SpringBootauto-configuresaThreadPoolTaskExecutorwithsensibledefaultsthatcanbeautomaticallyassociatedtoasynchronoustaskexecution(@EnableAsync)andSpr......
  • 32. Spring Boot使用@SpringBootApplication注解【从零开始学Spring Boot】
     如果看了我之前的文章,这个节你就可以忽略了,这个是针对一些刚入门的选手存在的困惑进行写的一篇文章。很多SpringBoot开发者总是使用@Configuration,@EnableAutoConfiguration和@ComponentScan注解他们的main类。由于这些注解被如此频繁地一块使用(特别是你遵循以上最佳实践时),S......
  • springboot下的@NotBlank,@NotNull,@NotEmpty
    话不多说1.三个注解区别@NotBlank只能作用在String上,不能为null,而且调用trim()后,长度必须大于0(不能为空格)@NotNull不能为null,但可以为空字符串,校验Integer类型不能为空@NotEmpty不能为null,并且长度必须大于0,校验List类型不能为空2.依赖引入`<dependency> ......
  • springboot自动装配
    1、自动装配是什么及作用springboot的自动装配实际上就是为了从spring.factories文件中获取到对应的需要进行自动装配的类,并生成相应的Bean对象,然后将它们交给spring容器来帮我们进行管理2、spring自动装配的原理2.1、启动类上注解的作用@SpringBootApplication这个注解是spri......
  • springboot框架介绍,让我们深入的了解
    ​ SpringBoot是一种用于快速构建基于Spring框架的Java应用程序的开源框架。它旨在简化Spring应用程序的开发过程,通过提供一种约定优于配置的方式,让开发人员能够快速搭建起一个可独立运行的、可部署的、易于扩展的应用。SpringBoot内置了许多开箱即用的功能和插件,使得开发者......
  • 第三天(SpringBoot项目部署,简单HelloWorld,打包,yaml,注入配置文件,多环境配置)
    老师的文档里大部分都写得很清楚,此处只做部分补充此处JDK应选1.8版本的,版本太高有几率出错添加启动web的依赖添加insert+alt快速配置constructorgettersettertostring松散绑定检验矫正依赖添加......