Springboot 獲取jar包中的檔案

紅燒鯉魚發表於2018-09-19

Springboot 複製jar包中的檔案

在spring專案中,如果以war包的方式執行在tomcat中,在執行前會把war包解壓到webapps目錄下,resource下的檔案也會以普通檔案的形式存在,如果有一些特殊檔案需要讀取/執行/使用,則以正常的file形式讀取就可以。 但springboot以jar包方式執行,若是想獲取resource下的某些靜態檔案,有以下幾種方式:

  • 1.resourceload的方式讀取
  • 2.unzip解壓部分jar包中的檔案
  • 3.jar 命令解壓整個jar包

第一種方式可以獲取一些靜態資源的內容,以io流的方式讀取並使用,但是不能執行,例如resource下有一個adb,則需要用流的方式複製到檔案系統內,才能繼續執行。如果這樣的檔案較多且目錄比較複雜,還需要遞迴複製。

第二種方式在windows與linux中不相容,均需要依賴相關的unzip工具

第三種方式只需要jre,比較通用,但會解壓整個jar包。

本文主要介紹第三種方式。

jar命令介紹

jar命令引數:

jar命令格式:jar {c t x u f }[ v m e 0 M i ][-C 目錄]檔名...

其中{ctxu}這四個引數必須選選其一。[v f m e 0 M i ]是可選引數,檔名也是必須的。

引數 作用
-c 建立一個jar包
-t 顯示jar中的內容列表
-x 解壓jar包
-u 新增檔案到jar包中
-f 指定jar包的檔名
-v 生成詳細的報造,並輸出至標準裝置
-m 指定manifest.mf檔案.(manifest.mf檔案中可以對jar包及其中的內容作一些一設定)
-0 產生jar包時不對其中的內容進行壓縮處理
-M 不產生所有檔案的清單檔案(Manifest.mf)。這個引數與忽略掉-m引數的設定
-i 為指定的jar檔案建立索引檔案
-C 表示轉到相應的目錄下執行jar命令,相當於cd到那個目錄,然後不帶-C執行jar命令
  • jar -cvf hello.jar hello
    建立並顯示打包過程
  • jar -xvf hello.jar
    解壓jar包並顯示過程

我們需要用到的就是jar -xf命令

在springboot中解壓jar包,並獲取jar包中的resource的目錄

先上程式碼:

import lombok.extern.slf4j.Slf4j;

import java.io.File;
import java.io.IOException;
import java.util.Arrays;

@Slf4j
public class PathUtil {

    private static final String SPEA = java.io.File.separator;

    /**
     * 除錯時輸出:D:\workspace\copyfilesfromjar
     * windows jar包輸出: D:\workspace\copyfilesfromjar\target
     * linux jar包輸出:/home/dongweihang
     *
     * @return 返回jar執行目錄
     */
    public static String getApplicationClassPath() {
        return System.getProperty("user.dir");
    }

    /**
     * @return 返回resources目錄(需要提前把jar包中的檔案解壓到系統目錄中)
     */
    public static String getResourcePath() {
        File file = new File(getApplicationClassPath());
        if (file.exists() && file.isDirectory() && file.listFiles() != null) {
            String jarFileName = Arrays.stream(file.listFiles()).map(File::getName).filter(s -> s.contains(".jar")).findFirst().orElse(null);
            String resourcePath = null;
            if (jarFileName != null) {
                //如果目錄下包含jar ,說明是用jar包執行的,先用jar -xf解壓
                try {
                    Process process = Runtime.getRuntime().exec("jar -xf " + jarFileName);
                    process.waitFor();
                } catch (IOException | InterruptedException e) {
                    log.info("can not exec jar -xf");
                    e.printStackTrace();
                    return null;
                }
                resourcePath = file.getAbsolutePath().concat(SPEA).concat("BOOT-INF").concat(SPEA).concat("classes").concat(SPEA);
                return resourcePath;
            } else {
                //不包含jar,說明在除錯模式中 後接\target\classes
                resourcePath = file.getAbsolutePath().concat(SPEA).concat("target").concat(SPEA).concat("classes").concat(SPEA);
                return resourcePath;
            }
        }
        return null;
    }
}
複製程式碼

首先通過System.getProperty("user.dir")獲取到jar包的執行目錄,這裡要注意在除錯時不會用jar包執行,因此目錄下不存在jar,相應的resource檔案也已經在target/classes下,以普通檔案存在。因此這種情況不需要解壓jar包。

那麼只要是以jar包形式執行,通過Runtime.getRuntime().exec("jar -xf " + jarFileName)解壓jar包之後,相應的檔案會存在在/BOOT-INF/classes下。

例如我將需要使用的檔案放在resource下的file目錄下

Springboot 獲取jar包中的檔案
在解壓後會在

Springboot 獲取jar包中的檔案

解壓後我們操作這些檔案就可以按照file 的方式來操作了。

相關文章