解決SpringBoot jar包中的文件讀取問題實現(xiàn)
前言
SpringBoot微服務已成為業(yè)界主流,從開發(fā)到部署都非常省時省力,但是最近小明開發(fā)時遇到一個問題:在代碼中讀取資源文件(比如word文檔、導出模版等),本地開發(fā)時可以正常讀取 ,但是,當我們打成jar包發(fā)布到服務器后,再次執(zhí)行程序時就會拋出找不到文件的異常。
背景
這個問題是在一次使用freemarker模版引擎導出word報告時發(fā)現(xiàn)的。大概說一下docx導出java實現(xiàn)思路:導出word的文檔格式為docx,事先準備好一個排好版的docx文檔作為模版,讀取解析該模版,將其中的靜態(tài)資源替換再導出。
docx文檔本身其實是一個壓縮的zip文件,將其解壓過后就會發(fā)現(xiàn)它有自己的目錄結(jié)構(gòu)。
問題
這個docx文檔所在目錄如下圖所示:
在本地調(diào)試時,我使用如下方式讀?。?/p>
import org.springframework.util.ResourceUtils; public static void main(String[] args) throws IOException { File docxTemplate = ResourceUtils.getFile("classpath:templates/docxTemplate.docx"); }
可以正常解析使用,但是打包發(fā)布到beta環(huán)境卻不可用。拋出異常如下:
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包解壓過后,發(fā)現(xiàn)這個文件是真真實實存在的。
那這到底是怎么回事呢?這壓根難不倒我。我們要善于透過堆棧信息看本質(zhì)。通過仔細觀察堆棧信息,我發(fā)現(xiàn)此時的文件路徑并不是一個合法的URL(文件資源定位符)。原來jar包中資源有其專門的URL形式: jar:<url>!/{entry} )。所以,此時如果仍然按照標準的文件資源定位形式
File f=new File("jar:file:……");
定位文件,就會拋出java.io.FileNotFoundException。
解決
雖然我們不能用常規(guī)操作文件的方法來讀取jar包中的資源文件docxTemplate.docx,但可以通過Class類的getResourceAsStream()方法,即通過流的方式來獲取 :
public static void main(String[] args) throws IOException { InputStream inputStream = WordUtil.class.getClassLoader().getResourceAsStream("templates/docxTemplate.docx"); }
拿到流之后,就可以將其轉(zhuǎn)換為任意一個我們需要的對象,比如File、String等等,此處我要獲取docxTemplate.docx下的目錄結(jié)構(gòu),因此我需要一個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的工具類即可轉(zhuǎn)換 FileUtils.copyToFile(inputStream,docxFile); ZipFile zipFile = new ZipFile(docxFile); Enumeration<? extends ZipEntry> zipEntrys = zipFile.entries(); // todo 記得關閉流 }
結(jié)果
打包、發(fā)布至beta環(huán)境,親測可用,問題完美解決。
到此這篇關于解決SpringBoot jar包中的文件讀取問題實現(xiàn)的文章就介紹到這了,更多相關SpringBoot jar包文件讀取內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
java 定時同步數(shù)據(jù)的任務優(yōu)化
這篇文章主要介紹了java 定時同步數(shù)據(jù)的任務優(yōu)化,幫助大家更好的理解和使用Java,感興趣的朋友可以了解下2020-12-12java對list<Object>進行手動分頁實現(xiàn)
本文主要介紹了java對list<Object>進行手動分頁實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2022-07-07- SpringCloudAlibaba是一款優(yōu)秀的微服務架構(gòu),在市面上有著廣泛的應用,這篇文章介紹了SpringCloudAlibaba的一些基本使用,適合初學者,希望能夠給大家?guī)韼椭?/div> 2024-08-08
如何自定義Jackson序列化?@JsonSerialize
這篇文章主要介紹了如何自定義Jackson序列化?@JsonSerialize,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-12-12SpringBoot項目報錯:"Error?starting?ApplicationContext....
這篇文章主要給大家介紹了關于SpringBoot項目報錯:“Error?starting?ApplicationContext.?To?display?the?conditions?report?re-run?...”的解決辦法,文中通過圖文介紹的非常詳細,需要的朋友可以參考下2022-08-08最新評論