簡體   English   中英

無法讀取spring boot包裝jar文件

[英]Can not read spring boot packaging jar file

環境:Ubuntu 18 + Spring boot 2.0 + JDK 11

當應用程序在IntelliJ中運行時,它可以正確執行,但是在Spring boot maven插件打包文件之后讀取文件時,它不能運行。

PS:確實可以在打包的jar文件中找到該文件!

java.io.FileNotFoundException: class path resource [jmxremote.password] 
cannot be resolved to absolute file path because it does not reside in the 
file system: jar:file:/home/XXX/YYY/target/YYY-1.0-Final.jar!/BOOT-
INF/classes!/jmxremote.password

您最有可能嘗試使用java.io類加載類路徑資源。 這是行不通的, java.io類僅用於文件系統操作。

提取jmxremote.password之外的jmxremote.password或使用常規InputStream作為類路徑資源來訪問它,例如通過使用Class.getResourceAsStream()

try (InputStream in : getClass().getResourceAsStream("/jmxremote.password")) {
  // read input
}

TL; DR

在Spring Framework環境中,重點是使用Spring實用工具來處理資源(例如ResourceUtils ),該ResourceUtils很好地封裝了底層的,與操作系統相關的IO操作。 ResourceUtils已經包含多個陷阱,以確定正在運行的項目是分解 (在IDE中運行)還是打包 (在JAR文件中)。


Karol提供的答案似乎最簡單並且相對防彈,直到您需要某種程度的靈活性來指定文件位置(在jar文件中,但可以在外部定義它並在文件系統中的某個位置提供)。 然后,帶有getResourceAsStream()方法的方法將不起作用。

標准Java IO( java.nio )使用FileSystemProvider類委派IO操作(如創建,讀取和刪除文件)。

提供者由URI 方案標識。 默認提供程序由URI方案“文件”標識。 它創建FileSystem,該文件系統提供對Java虛擬機可訪問的文件系統的訪問。 FileSystems類定義如何定位和加載文件系統提供程序。

因此,如果您的文件位於文件系統上的某個位置,則沒有問題,並且一切正常。 從技術上講,由Application.class.getResource("").toURI()返回的URL以file://開頭,並包含有效的文件系統路徑。

話雖如此,當您的文件“降落”在jar文件中時, Application.class.getResource("").toURI()返回的內容類似於file:// {jar-location}!/ (注意感嘆號) ,這不是有效的文件架構路徑,並且Java不知道如何處理它。 其他文件系統提供者需要注冊。

FileSystems.newFileSystem(uri, emptyMap());

Java(基於URI)找出方案並注冊一個新的文件系統。 從現在開始,可以使用標准的java.nio文件操作。

例如,如果您在/ webapp文件夾中有一些文件,這些文件可以(但不必)位於jar文件中,並且您希望列出它們。

// Load zip specific filesystem provider when run from inside a fat-jar
URI uri = Application.class.getResource("").toURI();
if (uri.toString().contains("!")) {
    FileSystems.newFileSystem(uri, emptyMap());
}

URI rootFolder = Application.class.getResource("/webapp").toURI();
List<Path> banners = Files.list(Paths.get(rootFolder))
        .collect(Collectors.toList());

Random rand = new Random();
Path path = banners.get(rand.nextInt(banners.size()));

log.info("Random image: {}", path.getFileName());
byte[] bytes = Files.readAllBytes(path);

新文件系統提供程序的安裝是全局的,並且只能執行一次。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM