拒絕FileNotFoundException!幾個讀取jar包外配置檔案的知識點

前言

相信很多人遇到過這個問題:本地執行的好好的程式,怎麼部署到線上就報找不到配置呢?

初識getResource

案例一

FieldMapConfig。class。getResource(“p1。properties”)。getPath(); - 這段程式碼在本地執行沒有任何問題,一放到線上就報空指標。案例二

拒絕FileNotFoundException!幾個讀取jar包外配置檔案的知識點

讀取配置,報錯FileNotFoundException。

乍一看,兩段程式碼好像沒有什麼區別,但是細心的你,應該發現:

App。class。getClassLoader()。getResource(“p1。properties”)。getPath();FieldMapConfig。class。getResource(“p1。properties”)

一個使用當前class的api,一個使用的當前class的classLoader的api來獲取的,這有什麼區別呢?請聽我細細分說。

Class和ClassLoader

秉著探索的態度,我寫了一個例子,請看:

public static void main( String[] args ) { if (args。length != 1) { System。out。println(“usage: java -jar com。hyq。simple-1。0。jar args”); return; } System。out。println(“App。class。getResource(args[0]):”); System。out。println(App。class。getResource(args[0])); System。out。println(); System。out。println(“App。class。getClassLoader()。getResource(args[0]):”); System。out。println(App。class。getClassLoader()。getResource(args[0])); System。out。println(); System。out。println(“App。class。getResourceAsStream(args[0]):”); System。out。println(App。class。getResourceAsStream(args[0])); System。out。println(); System。out。println(“App。class。getClassLoader()。getResourceAsStream(args[0]):”); System。out。println(App。class。getClassLoader()。getResourceAsStream(args[0])); System。out。println(); }

驗證如下:

拒絕FileNotFoundException!幾個讀取jar包外配置檔案的知識點

從上圖可以看出,使用當前類的GetResource和當前類的classloader的getResource,

獲取到的配置有區別。怎麼解釋呢?

前者是讀取的當前類的包目錄下的配置檔案

後者讀取的是,jar包內部,根目錄的配置檔案。

總結:當讀取配置的路徑不是以/開頭時,會按相對路徑讀取,相對的是當前類的class 這個檔案,而採用class的classLoader則是相對於根路徑(也就是我們說的classpath)。

各種路徑試驗

如果你還在為相對路徑,配置檔案前面帶不帶/,等一系列問題折騰,那不如動手做做試驗看看,程式碼還是上面那段程式碼,透過動態傳入配置檔案的路徑來讀取,試驗結果如下:

拒絕FileNotFoundException!幾個讀取jar包外配置檔案的知識點

為什麼推薦使用getResourceAsStream?

形如:“jar:file:/data/simpleJava/com。hyq。simple-1。0。jar

!/p1。properties” 這樣的路徑,getResource是無法讀取的,因為他不是一個檔案路徑。

而getResourceAsStream會以流的方式,開啟檔案來讀取資料,上圖的檔案樹,就是我用unzip命令解壓jar包後顯示出來的。

springboot載入配置

預設情況下,springboot會載入名為application的properties或者yml檔案。其中查詢的順序為:

1、當前jar包所在目錄的config目錄下。

2、當前目錄。

3、jar包內classpath的config目錄。

4、jar包內classpath目錄。

注意:重複定義的配置,會被後者覆蓋。

透過名字動態載入配置?

知識點一

boot配置的語法是,凡是以——開頭(兩個橫線)的配置,會被解析。

相信大家可能遇到過這樣一個場景,同一個jar包要啟動多次,每個程序的配置不一樣,埠不同。

拒絕FileNotFoundException!幾個讀取jar包外配置檔案的知識點

知識點二

透過——spring。config。name 指定配置檔名即可。還有一種新奇的方式,直接透過spring。application。json傳遞json,案例如下:

java -Dspring。application。json=‘{“name”:“test”}’ -jar myapp。jar

知識點三

當然,你也可以指定多個配置檔案,方式如下:

java -jar myproject。jar ——spring。config。location=classpath:/p1。properties,classpath:/p2。properties

值得注意的是,config配置檔案搜尋的順序和指定的順序是剛好相反的。

知識點四

透過spring。profiles。active屬性可以指定那個環境下的配置。

這裡我比較喜歡定義兩個yml,然後在application。yml中指定對應環境的配置。

spring: profiles: active: prod知識點五

可以透過@value註解來獲取變數值

@Value(“${app。init。welcome-msg:俠夢的開發筆記}”)private String msg;

也可以透過@ConfigurationProperties(“app。init”)註解,放在類來獲取整個配置。

總結

本章節我們做了實驗,瞭解了getResource和getResourceAsStream的區別。

學習了springboot透過動態指定配置名,讀取配置。

指定讀取多個配置檔案。

不同執行環境獲取不同配置的方式。

歡迎來公眾號【俠夢的開發筆記】 一起交流進步