<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          解決SpringBoot jar包中的文件讀取問題

          共 1963字,需瀏覽 4分鐘

           ·

          2020-08-26 19:31

          前言

          SpringBoot微服務(wù)已成為業(yè)界主流,從開發(fā)到部署都非常省時省力,但是最近小明開發(fā)時遇到一個問題:在代碼中讀取資源文件(比如word文檔、導出模版等),本地開發(fā)時可以正常讀取 ,但是,當我們打成jar包發(fā)布到服務(wù)器后,再次執(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)試時,我使用如下方式讀取:

          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:!/{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)換為任意一個我們需要的對象,比如FileString等等,此處我要獲取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?zipEntrys?=?zipFile.entries();
          ????????//?todo?記得關(guān)閉流
          ????}

          結(jié)果

          打包、發(fā)布至beta環(huán)境,親測可用,問題完美解決。

          最后

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

          • 1級:微辣
          • 2級:中辣
          • 3級:重辣
          • 4級:變態(tài)辣
          • 10級:你又一個人過七夕辣!
            天下有情人終成眷屬!祝大家早日脫單!??


          < END >
          程序員小明
          一個很少加班的程序員
          微信掃描二維碼,關(guān)注我的公眾號
          瀏覽 695
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  天天干天天噜天天操 | 国产一卡二卡在线观看 | 国产精品嫩草视频 | 欧美黑人性爽 | 免费A片国产毛无码A片 |