開心一刻
今天和相親物件見面,特意打扮了一番
見完面回到家後我給她發微信
我:我今天的形象怎麼樣
她:挺白淨亮眼的
我:頭髮不油吧
她:反光,沒看清
我:???
知識回顧
在我們的實際開發工程中,打包的 jar 通常會包含配置檔案(例如:application.yml
)來作為預設配置檔案,然後在不同的環境用外部配置檔案來覆蓋 jar 包中配置檔案配置的某些配置項,當然也可以全量覆蓋;Spring Boot 關於外部配置(Externalized Configuration)有這麼一段說明
我給大家翻譯一下
應用啟動時,Spring Boot會自動從以下位置查詢並載入
application.properties
和application.yaml
從類路徑
a. 類路徑根目錄
src/main/resources
下的檔案,預設情況下會被打包到類路徑(classpath)下b. 類路徑下的
config
包從當前目錄
a. 當前目錄,也就 jar 所在目錄
b. 當前目錄下的
config
目錄c. 當前目錄下的
config
目錄的直接子目錄Spring Boot 會按如上順序從上往下查詢並載入
application.properties
和application.yaml
,如果配置項重新命名了,後載入的值會覆蓋掉之前載入的值。配置檔案中的配置項會以PropertySources
例項的形式新增到 Spring 環境中
我們來看個示例:spring-boot-external-config,程式碼非常簡單,我們只需要關注 ConfigDemo.java
/**
* @author: 青石路
*/
@Component
public class ConfigDemo implements InitializingBean {
private static final Logger LOGGER = LoggerFactory.getLogger(ConfigDemo.class);
@Value("${retry.times}")
private Integer retryTimes;
@Value("${http.url}")
private String httpUrl;
@Override
public void afterPropertiesSet() throws Exception {
LOGGER.info("retryTimes:{}, httpUrl:{}", retryTimes, httpUrl);
}
}
application.yml
內容如下
retry:
times: 6
http:
url: http://localhost:8080
我相信你們都能看懂,透過 Spring 注入進來兩個配置項(retry.times
和 http.url
)值,當應用中的全部屬性都設定完成之後,Spring 會呼叫 afterPropertiesSet
方法,日誌輸出 retryTimes
和 httpUrl
的值。結合上述的載入順序,我們來驗證下是否如 Spring Boot 官方所說
-
從類路徑
這個我們只驗證一種情況:類路徑下只存在
application.yml
;驗證非常簡單,直接在 jar 所在目錄下執行
java -jar spring-boot-external-config-1.0-SNAPSHOT.jar
可以看到輸出如下
是不是沒毛病?
-
從當前目錄
在 jar 所在目錄下放一個
application.yml
其內容如下
retry: times: 2
我特意拿掉了配置項
http.url
,同樣直接執行java -jar spring-boot-external-config-1.0-SNAPSHOT.jar
輸出結果如下
紅框框住的值與藍框框住的值,它們分別來自哪個配置檔案,你們應該知道吧;也如 Spring Boot 官方所說,非常正常。我們再在當前目錄下加個
config
目錄其下放一個
application.yml
,內容如下retry: times: 9 http: url: http://127.0.0.1:8080
執行結果如下
也如 Spring Boot 官方描述的那樣,沒有任何毛病
為了保持部署結構的簡單清晰,我們往往會採用
config
目錄的這種方式來放外部配置檔案,包括應用配置檔案、日誌配置檔案等等;但如果外部配置檔案跟當前目錄沒有直接關係了,比如在其他盤或者其他目錄下,那麼如何指定外部配置檔案呢?有但不限於如下兩種(仔細斟酌如下寫法是否正確)- java -jar spring-boot-external-config-1.0-SNAPSHOT.jar -Dspring.config.location=外部檔案路徑
- java -jar spring-boot-external-config-1.0-SNAPSHOT.jar --spring.config.location=外部檔案路徑
外部檔案按路徑可以是絕對路徑,也可以是相對路徑,如果是相對路徑,則以 jar 包所在的目錄開始算
復現問題
一切準備就緒,我們往 Linux
伺服器上部署,先將 spring-boot-external-config-1.0-SNAPSHOT.jar
上傳到伺服器,執行
java -jar spring-boot-external-config-1.0-SNAPSHOT.jar
日誌輸出如下
這是 jar 中預設配置檔案的配置值,沒問題吧?我們再上傳 jar 同級目錄下的 config 資料夾,上傳後目錄結構如下
執行後日志輸出如下
也和在 windows 上的演示結果一樣,很正常。絕大部分情況下,我們的配置檔案不止一個,所以從命名的準確性考慮,我們往往會將 config
目錄命名成 configs
那麼此時啟動命令就需要調整下了
java -jar spring-boot-external-config-1.0-SNAPSHOT.jar -Dspring.config.location=configs/application.yml
或
java -jar spring-boot-external-config-1.0-SNAPSHOT.jar --spring.config.location=configs/application.yml
我們以 -D
的形式啟動下,日誌輸出如下
這輸出的還是 jar 包中的配置項值,並非 configs 目錄下 application.yml 中的配置項值,讀取外部配置檔案失敗了?帶著疑問我們嘗試下 --
方式
java -jar spring-boot-external-config-1.0-SNAPSHOT.jar --spring.config.location=configs/application.yml
發現能夠正常載入
為什麼 -D
的方式會失敗?
解決問題
出題出在哪,就出在 java 命令引數的順序上,我們看下 java
命令的幫助文件
也就是說 -D
或 --
需要在 -jar
前面,所以正確讀取 configs 目錄下配置檔案的命令應該是
java -Dspring.config.location=configs/application.yml -jar spring-boot-external-config-1.0-SNAPSHOT.jar
執行結果如下
總結
-
常用載入外部配置檔案的命令引數
java -Dspring.config.location=configs/application.yml -jar spring-boot-external-config-1.0-SNAPSHOT.jar
或
java -jar spring-boot-external-config-1.0-SNAPSHOT.jar --spring.config.location=configs/application.yml
-D
緊隨java
之後,在-jar
之前,是 JVM 引數;--
在 jar 名稱之後,是 Spring Boot 命令列引數。兩種方式有其各自的順序寫法,切勿張冠李戴! -
推薦做法
在 jar 包所在目錄建立
config
資料夾,將外部配置檔案置於該 config 資料夾下,啟動的時候可以減少啟動引數,那麼出錯的機率就會降低