來源:https://lepdou.github.io/blogs/config/config.html
引言
項目開發中總是有各種各樣的配置,對於程序開發新手來說,配置是擺在面前的第一座大山。 回想當年在學校學習經典的“SSH”的時候,一個web.xml配置都是異常的艱辛。工作多年的你,對配置真的瞭解嗎?
什麼是配置?
首先我們來看一下配置文件的定義:
“A software file used to configure the initial settings for a computer program.” -- From wikipedia
配置來源可能有以下這些:
- 硬編碼參數
- 項目裏的配置文件
- 文件系統上的配置文件
- 網絡上的配置文件
- 啓動參數(JVM屬性)
- 操作系統參數
下面會詳細介紹每一種配置類型的使用場景。
硬編碼參數
最常見的就是定義靜態變量方式。例如: public static final int PAGE_SIZE = 10;
另外就是通過框架暴露的各種API接口設置參數。
優點
- 這種是最簡單、成本最低的方式
- 不用額外創建文件
- 代碼裏能直接能讀取
- 離配置使用地方最近的一種方式
缺點
- 代碼和配置糅合在一起,不易於維護
- 修改配置必須修改源代碼,重新編譯、打包、上線
- 同一個框架的配置散落到項目各個角度,不利於查找
適用場景
- Hard Code 適用於配置極其簡單且幾乎不會變更
- 爲了賦予常量語義
- 配置極少從而創建配置文件成本高
項目裏配置文件
這種方式是最常見的。標準的maven項目有一個resources目錄就是用來放置各種類型的配置文件,例如:
- web項目的web.xml
- log框架的配置
- spring的bean定義的xml文件
- mybatis的sql配置文件
- spring boot的application.yml application.properties
- 自定義的properties文件
另外maven項目的核心pom.xml也算是配置文件。項目裏使用到的各種各樣的框架、中間件基本上都需要配置文件來支撐。框架在運行時,讀取配置文件來決定運行時的行爲。 配置文件路徑一般有兩種方式:
- 按照框架約定的目錄(相對於classpath)
- 告訴框架配置文件的路徑
優點
- 配置和代碼分離
- 集中統一管理配置
- 不依賴項目外部資源
缺點
- 跟Hard Code一樣不能動態修改配置
- 配置文件增生,導致項目臃腫
適用場景
- 非常適合框架或者中間件的配置
- 項目中自定義業務配置
文件系統上的配置文件
此類配置文件是放在應用運行的機器上。常見的比如攜程公司內部機器上都會放置一個server.properties文件。文件內容主要是當前機器的一些信息,比如env=dev標示當前機器屬於dev環境。公司配套提供framework-fundation基礎jar包,用來解析這個文件。
那麼應用只要通過framework-foundation來獲取機器的相關信息。 framework-foundation在這裏的作用就是作爲機器和應用之間的橋樑。這種方式主要好處是規範運維。 另外一種使用比較多的場景是應用直接讀取文件系統上的某個文件。這種方式的好處就是可以動態更新配置,無需重新編譯、打包、運行應用。
優點
- 配置和代碼分離
- 可動態修改配置
缺點
- 配置和應用代碼不在一個地方(項目源碼),不易於理解和運行
- 修改配置需要登錄機器
- 修改配置文件可能涉及權限問題
- 配置文件路徑也需要溝通
適用場景
- 不建議作爲應用業務相關的配置,成本高且不易於開發維護
- 適用於運維相關的配置,如前面舉的例子
筆者遇到過一個dal框架,datasource配置文件就是放在文件系統上,結果開發人員在上線時,忘記在機器上放置這個文件導致線上bug。
網絡上的配置文件
常見的包括兩種:DB上的配置表、配置中心。如果公司沒有統一的配置中心,那麼最簡單的動態修改配置的方式莫過於把配置放置在DB上。相信大部分的開發都使用過或者遇到過。
配置中心是最適合集中化管理配置、動態修改配置的地方。常見的配置中心都會提供管理配置後臺、實時推送配置、分環境管理配置、配置版本管理等。筆者目前就在開發一款開源的配置中心繫統。
優點
- 集中管理配置、全方位管理配置
- 動態修改配置、實時推送、更新配置
- 配置更加靈活,例如可以分環境、集羣以及灰度發佈等
缺點
- 需要依賴數據庫或者配置中心,成本高
適用場景
- 經常需要變更的配置
- 配置值每個環境不一致
- 不希望配置值隨着代碼一起發佈,例如開源項目中的某些配置
啓動參數(JVM屬性)
JVM屬性主要是應用運行的JVM進程相關的屬性,比如java.class.version、java.class.path等Java相關的參數。在代碼裏,可以通過System.getProperty()獲取參數值。 另外,可以通過在啓動時指定-D參數來設置JVM屬性。最常見的使用場景是用來解決不同環境需要配置不同的參數。例如作爲中間件,依賴的外部系統越少越好,如果不依賴配置中心,那麼就可以通過這種方式來實現不同環境配置不同的參數,例如每個環境的數據庫連接串不一樣。 另外需要提到的是maven打包參數。
相比於-D運行時參數,maven打包參數是在編譯時設置配置屬性,maven會獲取打包參數然後替換掉配置文件裏的placeholder。假設一個可運行的jar包,只需要在打包的時候傳入參數值,打出來的jar包就可以到處運行了,如果不這麼做,那麼需要每次運行的時候指定參數,成本太高。使用方式則是在mvn package 時指定-D參數。 新手很容易混淆這兩種參數。換個角度看-D是命令行參數。
優點
- 以非常小的代價就可以達到運行時指定特殊參數值
缺點
- 啓動運行項目需要設置啓動參數,增加使用成本
適用場景
- 適合中間件類系統,不推薦業務系統使用(業務系統用配置中心解決此類場景)
- 增加統一運維成本
操作系統參數
操作系統參數一般是隻讀的,當然也可以設置。例如前面提到的server.properties文件裏的env參數,其實也可以作爲系統參數,但是不建議這麼做。
後記
配置的好處顯而易見,但是我們在工作中經常會遇到這種情況。拿到一個項目,看到亂七八糟的配置無從下手,項目中使用的框架、中間件配置風格更不相同,更頭疼的是配置項如果不瞭解框架的基礎上很難理解。
導致的結果就是如果不復制、粘貼配置,手寫配置基本上很難寫對。 驗證這種情況最簡單的方式就是不復制其它項目的配置,手動搭建一個新項目。我相信絕大多數的人都難以做到。
片面的說學習一個框架其實是在學習這個框架的API和配置參數。如果你非常熟悉一個框架的配置,那麼你對框架的使用就得心應手了。當然,知道框架的原理也非常重要。 說這麼多,只想說明項目的配置真的非常重要,更好的管理、規範配置更加重要。
對於框架、中間件開發者來說,配置應該越少越好,增加一個配置對於使用者使用成本就會大大提高。如果配置很多,那麼你的框架基本上就是很難用了。 Spring一直是Java界最權威的框架體系,最新的Spring Boot框架的配置就非常少,一眼看上去非常舒心。
Spring現在倡導減少配置文件,例如Spring早期版本的xml配置其實是很繁瑣的。新的Spring更多的配置放置在代碼中,利用註解以及API方式配置。Servlet最新版本也不需要web.xml文件了。
說明一個道理: 大道至簡?
近期熱文推薦:
1.1,000+ 道 Java面試題及答案整理(2022最新版)
4.別再寫滿屏的爆爆爆炸類了,試試裝飾器模式,這纔是優雅的方式!!
覺得不錯,別忘了隨手點贊+轉發哦!