javascript
Spring Boot 属性配置你所不知道的细节
今天我們要聊的這個問題,可能工作5年的資深程序員也不一定搞得很清楚,但是我敢保證在開發 Web 應用過程中大家都遇到過。
這個問題就是: Spring Boot 應用程序讀取配置屬性時,不同配置源的優先級是個啥情況?
那如果你對這個問題沒啥概念,我給大家說幾個場景,你肯定就明白了?
應用程序的數據庫配置,我們一般都是通過配置文件配置的?不會有人直接硬編碼寫的吧;
應用開發中往往都需要加一些開關來控制業務邏輯,比如新功能灰度之類的場景;
開發、測試、生產環境需要不同的值,這種變量一般也都是通過外置配置來讀取的,不會直接寫死的;
我想上面這幾種場景,搞過 Java 開發的總歸會遇到的,今天我們要聊的就是這些外置的配置屬性,配置在不同的地方,如果屬性名一樣的情況下,到底誰的優先級高?也可以說配置在高優先級地方的屬性值會覆蓋低優先級位置的同名屬性值。
說實話,這個問題我身邊很多工作了多年的資深開發都沒有搞明白,不過這個并不影響他們開發,大不了調試一波嘛,就是多費點時間。但是也有特別騷的情況,他們也頭大。
比如生產環境莫名其妙的出了問題,排查是因為一個配置屬性值不對導致的,但是測試環境看了沒問題,然后項目中的配置文件配置的也沒問題,這種就很煩人了。
排查到最后一般就會發現:生產環境的啟動命令加了命令行參數或者 JVM 系統屬性,比這還騷的就是配到了系統的環境變量里面。。
那今天這個問題搞懂了,就有以下幾個好處:
可以幫助你高效的開發出符合預期的應用程序;
在排查一些老代碼導致的異常時,多一個排查思路,看看是否是不同環境的屬性配置不同(經常有一些老項目的屬性值是配置在環境變量里,覆蓋了代碼里面的屬性配置);
提高開發效率(在不改項目配置的情況下,通過高優先級的屬性源覆蓋對應的屬性)
Spring Boot 常用的屬性源
下面列舉出我們平時常用的一些配置屬性源:
這些屬性源其實我已經按照優先級從高到低的順序排列了,也就是說命令行參數的優先級最高,其次是 JVM 系統屬性,默認屬性優先級最低,同名屬性將會遵循高優先級覆蓋掉低優先級。
這其實就是本文的最終結論了,后面就是介紹各種屬性源如何設置,進行實操驗證了。你如果不想往后看了,直接收藏這張圖片也是可以的哦~
這些屬性配置的方法部分小伙伴可能沒有用過,接下來我們用一個例子來實戰演示下,也推薦你動手實踐,試試結論是否正確,這樣理解記憶會更加深刻。
驗證配置屬性的優先級
為了能夠清晰高效的達到我們驗證各個屬性源配置屬性優先級的目的,這里的思路就是:先在低優先級的屬性源配置,然后配置高優先級,如果覆蓋了就說明我們的結論沒毛病。
首先我們使用 Spring Boot 快速寫一個簡單的 Web 接口,然后直接返回配置的屬性名:
@RestController public?class?ReadingListController?{//?獲取屬性配置的類@Resourceprivate?MyProperties?myProperties;@GetMapping("/getMaxValue")public?String?getProperties?()?{return?"配置的屬性值?=?"?+?myProperties.getMaxValue();} }上面我們使用了一個專門用來獲取配置屬性的 Bean,不建議直接在 Controller 引用屬性,這個大家平時在開發中也要注意下:
@Component @ConfigurationProperties(prefix=?"my"?) @Data public?class?MyProperties?{//?默認屬性值private?int?maxValue=?0;}那上面的代碼就是我們測試所需要的全部代碼了,接下來我們從最低優先級的屬性源開始配置。
默認屬性
這個不用多說,就是直接在 Java 代碼中聲明變量時賦予的值;
啟動應用程序后,訪問我們的測試接口:http://localhost:8000/getMaxValue
通過 @PropertySource 標注的屬性源
這種屬性配置的方法我們一般也經常用,就是自定義一個配置文件,然后用 @PropertySource 注解來指定加載。
上面的代碼,就會加載我們定義在 classpath 路徑下的 my.properties 文件了。我們在自定義的屬性配置文件 my.properties 中添加配置屬性:
my.maxValue=1然后重啟應用,訪問我們的測試接口,得到的輸出如下:
這就證明了 @PropertySource 屬性源配置覆蓋了默認配置。
application.properties配置文件
Spring Boot 應用程序,默認會加載 classpath 路徑下 application.properties 和 application.yml 文件中配置的屬性。這也是我們開發時最常用的屬性配置源了。
在重啟應用,訪問我們的測試接口,就會得到結果值 2 了。說明應用內的 application.properties 文件中配置的屬性優先級高于 @PropertySource 指定的自定義配置文件。
這里需要注意,如果 classpath 路徑下同時存在 application.yml 和 application.properties 文件,那么 application.yml 文件中的屬性優先級高于 application.properties,這一點大家也可以自己測試下。
操作系統環境變量
這是一種騷操作了,在不同的環境設置了不同的操作系統環境變量,任你看代碼找破天也是一頭霧水。所以下次出現不同環境配置屬性值不符合預期的場景,操作系統環境變量記著檢查下。
這里我使用的 zsh,可以使用 export 來設置臨時的操作系統環境變量,當然 bash 也可以這樣配置。
export?my_maxvalue=3?細心的同學發現了,變量的命令我使用了下劃線而不是點,這是因為操作系統對變量名稱的要求。
然后我們將應用打包,我這里使用的 gradle 來構建項目,只需要執行:gradle build , Spring Boot ?提供的 gradle 插件就會幫我們將所有需要的依賴打包到一起,得到一個可執行的 jar 包。
然后我們啟動應用程序:java -jar build/libs/spring-road02-0.0.1-SNAPSHOT.jar
訪問測試接口得到的值就是3了。
結論證明:操作系統環境變量配置的屬性優先級又高于上面我們所列舉的。
JVM系統屬性
這也是生產環境使用最多的一種差異化屬性設置方式,在應用程序的啟動腳本命令中指定屬性值,好處就是其他人不能隨意修改,一般只能運維人員來編寫的。常見于配置一些影響應用程序運行穩定性的參數,比如內存分配、GC參數等的配置。
還是使用上面我們打好的 jar 包,在運行時增加 JVM 系統屬性即可:
java?-Dmy.maxvalue=4?-jar?build/libs/spring-road02-0.0.1-SNAPSHOT.jar然后訪問測試接口得到的值就變為了4。
命令行屬性配置
這個和 JVM 系統屬性配置的使用場景差不多,只不過設置方式有點區別,直接看下命令行啟動配置就明白了:
java?-Dmy.maxvalue=4?-jar?build/libs/spring-road02-0.0.1-SNAPSHOT.jar?--my.maxvalue=5啟動后,我們繼續訪問測試接口看看結果:
結果證明,命令參數的優先級比 JVM 系統屬性優先級高,會將其覆蓋。
總結
通過今天的實踐學習,大家應該對 Spring Boot 屬性配置常見的幾種來源有了更加清晰的認識,并且通過實驗測試了它們具體的優先級。我們再來匯總整理下:
按照優先級的高低從上往下排列,也就是說命令行參數配置的屬性優先級最高,會覆蓋其它屬性源的配置,以此類推,記不住的小伙伴可以收藏下,以備不時之需。
今天就先聊到這里,更多關于 Spring 相關的內容,也在持續更新中,敬請關注!
有道無術,術可成;有術無道,止于術
歡迎大家關注Java之道公眾號
好文章,我在看??
新人創作打卡挑戰賽發博客就能抽獎!定制產品紅包拿不停!總結
以上是生活随笔為你收集整理的Spring Boot 属性配置你所不知道的细节的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: vue项目 预览照片的插件 v-view
- 下一篇: gradle idea java ssm