簡體   English   中英

Spring Boot jar 中的 FileNotFoundException 但文件存在

[英]FileNotFoundException in spring boot jar but the file is present

當文件明顯存在於 jar 中時,我收到 FileNotFoundException。 為什么會這樣?

java.io.FileNotFoundException: file:/Users/serviceuser/project/coolApp/target/coolApp-1.0-SNAPSHOT.jar!/BOOT-INF/classes!/ssl_certs/mysslstore.jks (No such file or directory)
    at java.base/java.io.FileInputStream.open0(Native Method) ~[na:na]
    at java.base/java.io.FileInputStream.open(FileInputStream.java:219) ~[na:na]
    at java.base/java.io.FileInputStream.<init>(FileInputStream.java:157) ~[na:na]
    at java.base/java.io.FileInputStream.<init>(FileInputStream.java:112) ~[na:na]

但是,我看到打包在 jar 中的文件。

jar -tf coolApp-1.0-SNAPSHOT.jar | grep ssl

在此處輸入圖片說明

編輯我加載文件如下

new FileInputStream(CoolApp.class.getClassLoader().getResource("ssl_certs/mysslstore.jks").getFile())

這里 :

new FileInputStream(CoolApp.class.getClassLoader().getResource("ssl_certs/mysslstore.jks").getFile());

getFile()在 jar 中包含的URL上調用。
因此,它提供了一個特定的File對象,因為它不是在File系統中可直接訪問的File

並且URL javadoc確認(重點是我的):

類 URL 表示統一資源定位符,即指向萬維網上“資源”的指針。 資源可以是簡單的文件或目錄,也可以是對更復雜對象的引用,例如對數據庫或搜索引擎的查詢

所以FileInputStream(File)構造函數不一定能夠打開那個“特殊”文件:

FileInputStream 從文件系統中的文件中獲取輸入字節。 哪些文件可用取決於主機環境。

您可以將您嘗試執行的操作與以下內容進行比較:

new FileInputStream("/Users/serviceuser/project/coolApp/target/coolApp-1.0-SNAPSHOT.jar!/BOOT-INF/classes!/ssl_certs/mysslstore.jks")

正如您所猜測的,操作系統文件系統無法解析 jar( mysslstore.jks ) 中包含的文件。

而不是使用返回輸入流的getResourceAsStream() 該輸入流指的是由資源表示的字節序列。 這樣,客戶端代碼不再依賴於資源的存儲方式。

InputStream is = CoolApp.class.getClassLoader().getResourceAsStream("ssl_certs/mysslstore.jks"));

像這樣的文件需要在資源目錄中。

I was facing the same issue in spring boot and I have tried many things like bellow but nun of them is working. thease all are working locally but  It is giving FileNotFoundException in dev environmnet because when we build a JAR, the resources get placed into the root directory of the packaged artifacts and our downloaded files I placed inside resource folder. 

Method 1: Working solution for jars
InputStream stram=getClass().getClassLoader().getResourceAsStream(File.separator+"database.properties");
URL url = getClass().getClassLoader().getResource(File.separator+"database.properties");

Only thing which worked is ResourceLoader. Need to Autowire it:
    @Autowired
    ResourceLoader resourceLoader;

        Resource resource = resourceLoader.getResource("classpath:" + File.separatorChar + NPIConstants.VAR_FOLDER
                + File.separatorChar + NPIConstants.TPSPIDsBUCKET_FILENAME);
        InputStreamResource isResource = new InputStreamResource(resource.getInputStream());

Method 1: Not Working solution for jars
ClassLoader loader = Thread.currentThread().getContextClassLoader();
InputStream is = loader.getResourceAsStream("database.properties");
System.out.println(is.available());

Method 2:  Not Working solution for jars
Resource resource = new ClassPathResource("database.properties");
InputStream input = resource.getInputStream();

Method 3: Not Working solution for jars
File file = new File("resources/database.properties");
String absolutePath = file.getAbsolutePath();

Method 4: Not Working solution for jars
File file = new File(getClass().getClassLoader().getResource("database.properties").getFile());

Method 5: Not Working solution for jars
ClassLoader classLoader = getClass().getClassLoader();
classLoader.getResource("database.properties");
String path  = classLoader.getResource("database.properties").getPath();

暫無
暫無

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

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