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

前言

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

背景

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

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

问题

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

在本地调试时,我使用如下方式读取:

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<? extends ZipEntry> zipEntrys = zipFile.entries();
        // todo 记得关闭流
    }

结果

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

最后

七夕啦~给大家科普一下辣的程度

  • 1级:微辣
  • 2级:中辣
  • 3级:重辣
  • 4级:变态辣
  • 10级:你又一个人过七夕辣! 祝天下有情人终成眷属!祝大家早日脱单!❤️ < END >

更多教程请访问码农之家    

  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Spring Boot是一个非常流行的Java框架,它可以轻松地将Java应用部署为独立的、自包含的可执行jar文件,包含了应用所有所需的依赖库。但是,有时候我们需要从可执行jar文件读取一些配置文件或者资源文件,这些文件在构建过程被打包进了jar包文件。那么该怎么读取这些文件呢? Spring Boot提供了一个非常简单的方式,只需要使用Spring框架的Resource类就可以轻松地实现。在Spring Boot使用Resource类来读取jar包文件,如下所示: ```java import org.springframework.core.io.Resource; import org.springframework.core.io.ClassPathResource; public class ReadFileFromJar { public static void main(String[] args) throws IOException { Resource resource = new ClassPathResource("config.properties"); InputStream inputStream = resource.getInputStream(); Properties properties = new Properties(); properties.load(inputStream); String value = properties.getProperty("key"); System.out.println(value); } } ``` 上面的代码,我们首先使用ClassPathResource类创建一个Resource对象,然后调用getInputStream()方法获取文件的输入流。最后,我们使用Properties读取属性文件的内容,并输出其的一个属性值。 注意:在使用Spring Boot的时候,所有的资源文件都需要放到classpath路径下,这样Resource类才能正确读取。在IDE集成开发环境,可以将这些文件放到src/main/resources目录下,或者配置maven的build过程将这些资源文件打包到jar文件

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值