[英]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.