前言

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. pandas_分类与聚合

    # 分组与聚合 import pandas as pd import numpy as np # 设置列对齐 pd.set_option("display.unicode.ambiguous ...

  2. 如何部署redis服务

    使用工具 redis-64-3.2.100 部署系统 windows server 2012R2 1.下载安装redis-64-3.2.100安装包,下载地址:https://github.com/m ...

  3. PHP sin() 函数

    实例 返回不同数的正弦: <?php高佣联盟 www.cgewang.comecho(sin(3) . "<br>");echo(sin(-3) . " ...

  4. 6.6 省选模拟赛 线段 二维数点问题 树套树 CDQ分治

    LINK:线段 还是太菜了 没看出这道题真正的模型 我真是一个典型的没脑子选手. 考虑如何查询答案. 每次在一个线段x的状态被更改后 可以发现有影响的是 和x相连那段极长连续1子段. 设这个子段左端点 ...

  5. NOI Online 游戏 树形dp 广义容斥/二项式反演

    LINK:游戏 还是过于弱鸡 没看出来是个二项式反演,虽然学过一遍 但印象不深刻. 二项式反演:有两种形式 一种是以恰好和至多的转换 一种是恰好和至少得转换. 设\(f_i\)表示至多的方案数 \(g ...

  6. idea查看类继承关系图

    找到对应的类 查看类关系图

  7. 畅购商城(五):Elasticsearch实现商品搜索

    好好学习,天天向上 本文已收录至我的Github仓库DayDayUP:github.com/RobodLee/DayDayUP,欢迎Star,更多文章请前往:目录导航 畅购商城(一):环境搭建 畅购商 ...

  8. hashMap在jdk1.7与jdk1.8中的原理及不同

    在分析jdk1.7中HashMap的hash冲突时,不知大家是否有个疑问就是万一发生碰撞的节点非常多怎么版?如果说成百上千个节点在hash时发生碰撞,存储一个链表中,那么如果要查找其中一个节点,那就不 ...

  9. 使用Azure人脸API对图片进行人脸识别

    人脸识别是人工智能机器学习比较成熟的一个领域.人脸识别已经应用到了很多生产场景.比如生物认证,人脸考勤,人流监控等场景.对于很多中小功能由于技术门槛问题很难自己实现人脸识别的算法.Azure人脸API ...

  10. Linux本地套接字(Unix域套接字)----SOCK_DGRAM方式

    目录 简述 创建服务端代码: 创建客户端代码 接收函数封装 发送封装 服务端测试main函数 客户端测试main函数 编译运行结果 简述 这里介绍一下Linux进程间通信的socket方式---Loc ...