前言

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环境,亲测可用,问题完美解决。

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

解决SpringBoot jar包中的文件读取问题的更多相关文章

  1. java读取jar包中的文件

    随手写了一个java小工具,maven打包成功后,发现工具总是读不到打在jar包中的文件信息,要读取的文件位于 /src/main/resources 目录下,打包成功后,文件就在jar包中根目录下, ...

  2. 使用命令动态更新JAR包中的文件

    动态更新JAR包中的文件,经本人实际测试可正常执行! 一.查询jar包中要替换的文件位置 jar  -tvf  gateway.jar  |  grep  topjui.config.js 二.在当前 ...

  3. 在swt中获取jar包中的文件 uri is not hierarchical

    uri is not hierarchical 学习了:http://blog.csdn.net/zdsdiablo/article/details/1519719 在swt中获取jar包中的文件: ...

  4. jar包中File 文件找不到的异常分析与解决

    源链接: http://hxraid.iteye.com/blog/483115#comments 我们常常在代码中读取一些资源文件(比如图片,音乐,文本等等).在单独运行的时候这些简单的处理当然不会 ...

  5. SpringBoot jar包中资源加载问题

    在IDE下调试怎么也没有发现问题,但是部署到服务器上,提示找不到资源,找了半天资料总算是找到了原因: Jar包中的资源加载不能使用File方式,只能使用InputStream方式读取.知道原因就好解决 ...

  6. Web项目替换jar包中的文件的方法

    经常遇到这样的问题,需要修改jar包中的方法.应该如何做? 1.有些很人性化的框架jar包,比如SpringSecurity,可以修改配置文件指定一个新建的类,让类实现Jar包中的对应的接口就好了. ...

  7. 修改jar包中class文件

    某日,想要更改jar包中的某个class文件,有无rar无法解压jar文件,故找到如下方式进行操作 1.解压某个jar包:在需要解压的jar包目录下,打开命令行(cmd),输入如下命令,输入:C:\j ...

  8. IDEA修改jar包中class文件后重新生成jar包

    一.背景 最新想要修改rebeyond大佬的冰蝎项目,特地去网上搜索如何修改jar包中的源码再替换回去的方法,但由于现在的一些文章写的太烂,导致走了很多弯路,因此写下这篇快速使用IDEA修改源码并替换 ...

  9. 解决SpringBoot jar包太大的问题

    转载 2017年09月18日 09:21:53 577 SpringBoot的web应用一般都添加了spring-boot-maven-plugin插件. Maven xml代码   <buil ...

随机推荐

  1. Numpy数组排序

    import numpy as np x = np.array([1,4,5,2]) # array([1, 4, 5, 2]) # 返回排序后元素的原下标 np.argsort(x) # array ...

  2. Skill 脚本演示 ycSchReGrid.il

    https://www.cnblogs.com/yeungchie/ ycSchReGrid.il 修复 schematic 或 schematicSymbol 视图中 offGrid 的问题. 回到 ...

  3. Python接口自动化测试框架: pytest+allure+jsonpath+requests+excel实现的接口自动化测试框架(学习成果)

    废话 最近在自己学习接口自动化测试,这里也算是完成一个小的成果,欢迎大家交流指出不合适的地方,源码在文末 问题 整体代码结构优化未实现,导致最终测试时间变长,其他工具单接口测试只需要39ms,该框架中 ...

  4. .NETCore微服务探寻(三) - 远程过程调用(RPC)

    前言 一直以来对于.NETCore微服务相关的技术栈都处于一个浅尝辄止的了解阶段,在现实工作中也对于微服务也一直没有使用的业务环境,所以一直也没有整合过一个完整的基于.NETCore技术栈的微服务项目 ...

  5. 比原链CTO James | Go语言成为区块链主流开发语言的四点理由

    11月24日,比原链CTO James参加了Go中国举办的Gopher Meetup杭州站活动,与来自阿里.网易的技术专家带来Kubernetes.区块链.日志采集.云原生等话题的分享.James向大 ...

  6. 强开企业付款到零钱与现金红包,无需等待90/30天,2-12H即可强开通!

    一.微信官方给出的,企业付款到零钱|现金红包开通的说明 针对入账方式为即时入账至商户号,结算周期为T+1的商户,需满足三个条件:1)入驻满90天,2)连续正常交易30天,3)保持正常健康交易.其余结算 ...

  7. JS中splice方法的使用

    在js中,arr.splice(str)方法是处理数组的利器,利用它可以实现在指定位置删除.替换.插入指定数量的元素. 其语法为:  arr.splice(index[, deleteCount, e ...

  8. C++实现二叉树的链接存储结构(先根、中根和后根遍历)

    验证二叉树的链接存储结构及其上的基本操作. [实验要求]: 1. 从文件创建一棵二叉树,并对其初始化: 2. 先根.中根.后根遍历二叉树: 3. 在二叉树中搜索给定结点的父结点: 4. 搜索二叉树中符 ...

  9. JavaScript npm/nrm 切换安装依赖的镜像源

    nrm: npm registry manager npm 镜像源管理工具 安装nrm npm install -g nrm 查看所有的镜像源 nrm ls # nrm ls npm -------- ...

  10. Vue Vuex 严格模式+实例解析+dispatch/commit + state/getter

    1.严格模式 import getters from './getters' import mutations from './mutations' import actions from './ac ...