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