解决SpringBoot jar包中的文件读取问题

前言

SpringBoot微服务已成为业界主流,从开发到部署都非常省时省力,但是最近小明开发时遇到一个问题:在代码中读取资源文件(比如word文档、导出模版等),本地开发时可以正常读取 ,但是,当我们打成jar包发布到服务器后,再次执行程序时就会抛出找不到文件的异常。

背景

这个问题是在一次使用freemarker模版引擎导出word报告时发现的。大概说一下docx导出java实现思路:导出word的文档格式为docx,事先准备好一个排好版的docx文档作为模版,读取解析该模版,将其中的静态资源替换再导出。

docx文档本身其实是一个压缩的zip文件,将其解压过后就会发现它有自己的目录结构。

问题

这个docx文档所在目录如下图所示:

解决SpringBoot jar包中的文件读取问题
在本地调试时,我使用如下方式读取:
import org.springframework.util.ResourceUtils;
    public static void main(String[] args) throws IOException {
File docxTemplate = ResourceUtils.getFile("classpath:templates/docxTemplate.docx");
    }

可以正常解析使用,但是打包发布到beta环境却不可用。抛出异常如下:

java.io.FileNotFoundException: class path resource [templates/docxTemplate.docx] cannot be resolved to absolute file path because it does not reside in the file system: jar:file:/usr/local/subject-server.jar!/BOOT-INF/classes!/templates/docxTemplate.docx

显而易见,这个异常告诉我们: 没有找到文件,但是将jar包解压过后,发现这个文件是真真实实存在的。
那这到底是怎么回事呢?这压根难不倒我。我们要善于透过堆栈信息看本质。通过仔细观察堆栈信息,我发现此时的文件路径并不是一个合法的URL(文件资源定位符)。原来jar包中资源有其专门的URL形式: jar:!/{entry} )。所以,此时如果仍然按照标准的文件资源定位形式

File f=new File("jar:file:......");

定位文件,就会抛出 java.io.FileNotFoundException

解决

虽然我们不能用常规操作文件的方法来读取jar包中的资源文件 docxTemplate.docx,但可以通过 Class类的 getResourceAsStream()方法,即通过流的方式来获取 :

    public static void main(String[] args) throws IOException {
InputStream inputStream = WordUtil.class.getClassLoader().getResourceAsStream("templates/docxTemplate.docx");
    }

拿到流之后,就可以将其转换为任意一个我们需要的对象,比如 FileString等等,此处我要获取 docxTemplate.docx下的目录结构,因此我需要一个 File对象,代码举例如下:

import org.apache.commons.io.FileUtils;

   public static void main(String[] args) throws IOException {
        InputStream inputStream = WordUtil.class.getClassLoader().getResourceAsStream("templates/docxTemplate.docx");
        File docxFile = new File("docxTemplate.docx");
        // 使用common-io的工具类即可转换
        FileUtils.copyToFile(inputStream,docxFile);
        ZipFile zipFile = new ZipFile(docxFile);
        Enumeration zipEntrys = zipFile.entries();
        // todo 记得关闭流
    }

结果

打包、发布至beta环境,亲测可用,问题完美解决。

本文可转载,但需声明原文出处。 程序员小明,一个很少加班的程序员。欢迎关注微信公众号,获取更多优质文章。

Original: https://www.cnblogs.com/coderxx/p/13566423.html
Author: Coder小明
Title: 解决SpringBoot jar包中的文件读取问题

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/610528/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • SpringBoot整合webSocket出现Are you running in a Servlet container that supports JSR-356?

    如果你使用的是SpringBoot自带的tomcat出现这种问题 那么换成别的容器就行了。 首先要将已经存在的容器排除掉 使用 exclusions 排除容器依赖 然后再添加别的容…

    Java 2023年5月30日
    068
  • 物联网架构成长之路(56)-SpringCloudGateway+JWT实现网关鉴权

    0. 前言结合前面两篇博客,前面博客实现了Gateway网关的路由功能。此时,如果每个微服务都需要一套帐号认证体系就没有必要了。可以在网关处进行权限认证。然后转发请求到后端服务。这…

    Java 2023年5月30日
    074
  • Skywalking-07:OAL原理——解释器实现

    OAL 解释器实现 OAL 解释器是基于 Antlr4 实现的,我们先来了解下 Antlr4 Antlr4 基本介绍 Antlr4 使用案例 参考Antlr4的使用简介这篇文章,我…

    Java 2023年6月5日
    081
  • 玩转SpringBoot之定时任务@Scheduled线程池配置

    序言 对于定时任务,在SpringBoot中只需要使用@Scheduled 这个注解就能够满足需求,它的出现也给我们带了很大的方便,我们只要加上该注解,并且根据需求设置好就可以使用…

    Java 2023年5月30日
    0132
  • spring security登录认证流程

    spring security登录认证流程 1、前端携带用户名和面膜发送请求,controller接收到后,调用service的login方法 2、根据传过来的用户名和密码生成Us…

    Java 2023年6月9日
    067
  • 多线程_基础

    一.一个Java程序最少开几个线程? 3个:主线程;gc线程;异常处理线程 二.线程的生命周期以及状态? 阻塞的分类: 等待阻塞:执行wait(),需要notify()/notif…

    Java 2023年6月7日
    077
  • 二、冯·诺依曼结构与快捷键的使用

    一、冯·诺依曼结构 二、快捷键的使用 Ctrl+A:全选Ctrl+C:复制Ctrl+V:粘贴Ctrl+X:剪切Ctrl+Z:撤销Ctrl+S:保存Alt+F4:关闭窗口Shift+…

    Java 2023年6月5日
    068
  • mongodb 数据块迁移的源码分析

    简介 上一篇我们聊到了mongodb数据块的基本概念,和数据块迁移的主要流程(详见mongodb数据块的迁移流程介绍),这篇文章我们聊聊源码实现部分。 迁移序列图 数据块迁移的请求…

    Java 2023年6月6日
    072
  • 线程让位与线程合并

    一、线程让位 Thread.yield();/是让当前线程赞停回到就绪状态,让给其他线程先执行,等执行之结束再继续执行 我们写个例子,一个t线程一个main线程,我们分别让两个线程…

    Java 2023年6月9日
    056
  • Redis基本操作

    windows 下载 https://github.com/microsoftarchive/redis/releases/tag/win-3.2.100 然后解压 打开服务 然后…

    Java 2023年6月7日
    058
  • 数组

    一.数组的定义格式 数组是存储同一种数据类型多个元素的容器。 数组既可以存储基本数据类型,也可以存储引用数据类型。 格式1:数据类型[] 数组名;(常用) 格式2:数据类型 数组名…

    Java 2023年6月5日
    081
  • 2022年【米哈游】 金三银四 三月社招内推开始啦!加班少福利好,200+个岗位任你挑选,赶快来看吧!

    米哈游 金三银四 三月内推开始啦 内推类型:社招(校招同学可以使用内推码NTAHEGf进行投递) 内推方式1:直接扫下方专属二维码或使用自助内推链接查看所有在招岗位,并进行投递 自…

    Java 2023年6月8日
    079
  • java环境配置

    一、环境配置 1、打开”开始->计算机->属性->高级系统设置->环境变量”2、设置环境变量(当前最新的是1.8.0_25),如下:…

    Java 2023年5月29日
    067
  • IDEA快捷键(windows)

    一、官方文档 IntelliJIDEA_ReferenceCard.pdf (jetbrains.com) 二、文档翻译 2.1 记住这些快捷键 REMEMBER THESE SH…

    Java 2023年6月8日
    065
  • nacos配置中心文件(bootstrap.properties)不生效问题解决

    springcloud整合nacos作为配置中心时,配置文件不生效的问题在这个问题处卡了一天多,在网上各种搜索。大多数解决方案都是在bootstrap.properties文件中配…

    Java 2023年6月7日
    085
  • S3上传时报错:Data read has a different length than the expected

    报错信息 使用S3上传文件时,发现存在几类报错。 第一种:Data read has a different length than the expected: dataLengt…

    Java 2023年6月5日
    048
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球