項目裏的各種配置,你都瞭解嗎?

來源: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

配置來源可能有以下這些:

  1. 硬編碼參數
  2. 項目裏的配置文件
  3. 文件系統上的配置文件
  4. 網絡上的配置文件
  5. 啓動參數(JVM屬性)
  6. 操作系統參數

(圖一 配置參數體系)

下面會詳細介紹每一種配置類型的使用場景。

硬編碼參數

最常見的就是定義靜態變量方式。例如: 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最新版)

2.勁爆!Java 協程要來了。。。

3.Spring Boot 2.x 教程,太全了!

4.別再寫滿屏的爆爆爆炸類了,試試裝飾器模式,這纔是優雅的方式!!

5.《Java開發手冊(嵩山版)》最新發布,速速下載!

覺得不錯,別忘了隨手點贊+轉發哦!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章