在很多系統中,需要用到設定檔來存放配置參數。配置參數從代碼中單獨提出來主要是為了方便修改用的。常見的一個用法是將資料庫連接參數(資料庫伺服器 IP,使用者名稱,密碼等等)寫在一個設定檔中,這主要是系統可能會更換資料庫,或者網路可能更換 IP 位址範圍,或者伺服器 IP 可能會變動等等。
配置參數不僅限於設定檔,也可以儲存在其他地方,比如資料庫單獨用一個表儲存配置參數,或者在記憶體中,或者在作業系統環境變數中,等等。有個現成的讀寫配置資料工具包,讓人感覺很不錯。
早期的設定檔主要用 ini 檔案,或者類似 ini 檔案格式。這種設定檔格式簡單,相應的讀寫工具類也很容易寫,各種開發語言基本上都能在網上找到現成的代碼。其主要特點是 key <--> value 對應。ini 檔案是純文字檔案,對於不是程式員的終端使用者,修改 ini 設定檔也沒有太多的難度。相比較而言,其他格式的配置都比 ini 有更大的難度。
可惜的是 Common Configuration 工具包不支援 ini 格式。文檔中說它支援的配置參數來源有:
* Properties files
* XML documents
* Property list files (.plist)
* JNDI
* JDBC Datasource
* System properties
* Applet parameters
* Servlet parameters
資料形式也不限於 key <--> value 形式,Common Configuration 工具包也支援樹形結構的參數配置。
Common Configuration 工具包體系比較簡單。一個基本的 Configuration interface 定義了各種配置通用的操作,一個 AbstractConfiguration 從 Configuration interface 下來將所有公用的操作實現了,留下一個不通用的函數 getProperty, setProperty 等待子類實現。真正有實際操作的 DatabaseConfiguration、PropertiesConfiguration、XMLConfiguration、XMLPropertiesConfiguration、MapConfiguration 等等,都是從 AbstractConfiguration 繼承。MapConfiguration 是基於記憶體操作的配置參數讀寫工具類,XMLPropertiesConfiguration 則是基於 XML 檔案的模仿 java properties 格式的設定檔讀寫工具類。有點怪吧?主要是因為 java property 檔案本來設計只是為了存放多語言字串用的,有的 java 程式員希望在 java 中有類似 INI 檔案的設定檔,但是 JDK 中沒有現成的工具類,只能用 property 檔案湊合著用。舉例來說, log4j 就可以用 property 格式的設定檔。但是這種格式的設定檔有個很大的弱點,如果裡麵包含非 ASCII 字元,比如說是中文,必須要寫成 UNICODE 編碼格式。如果軟體交付給使用者,使用者需要改一個參數,使用者沒有辦法改這種 property 檔案。XMLPropertiesConfiguration 使用的是 XML 格式設定檔,一般用 UTF-8 編碼,這種檔案可以用常用作業系統內建的軟體來修改(比如 windows 的記事本程式),因而更加方便。XML property 格式設定檔現在已經用得比較多了,在 J2SE 5.0 中也定義了一種 XML property 格式,這裡的 XMLPropertiesConfiguration 工具類就是遵循這種格式標準。
Configuration interface 定義了一些基本操作:addProperty, clear, clearProperty, containsKey, getBigDecimal, getBigInteger, getBoolean, getByte,getDouble,getFloat,getInt, getKeys, getList, getLong, getProperties, getProperty, getShort, getString, getStringArray, isEmpty, setProperty 等等。看起來還是比較齊全。也可以用 DataConfiguration 將已有的 Configuration 重新封裝一下,然後可以讀寫其它類型的配置參數:URL, Locale, Date, Calendar, Color, 以及各種形式對象的 lists 和 arrays。DataConfiguration 主要做的事情是在讀寫配置資料的時候將這些額外的類型資料與 String 類型相互轉換,最終所有配置參數還是儲存成 String 形式。
這裡面還有另外一個類 CompositeConfiguration, 可以將幾個 Configuration 並在一起用,這不太常見,偶爾會用到。舉例來說,將資料庫連接參數放在檔案型設定檔中,將系統其他參數放在資料庫中是一個比較常見的設計。如果幾個程式員同時偵錯工具,可能需要將資料庫中同一個配置參數設定成不同的值,這個時候就比較麻煩,要吵架了。這個時候可以將檔案型配置和資料庫配置做成一個組合配置CompositeConfiguration, 優先讀取檔案型配置中參數,如果檔案型配置參數中沒有才讀取資料庫中參數。這樣就可以解決了。真正最後系統交付的時候把所有配置放在資料庫中,只留下資料庫連接配置放在檔案型配置中。
值得注意的是,有的 Configuration 效能不夠最佳化,可能需要自己寫一個相應的子類將 getProperty, setProperty 等函數重新寫一下。現成的思路是,DatabaseConfiguration 每次 getProperty 都讀取一次資料庫,如果不是在叢集環境,可以把所有配置資料一次讀出放在一個 map 中,這樣每次 getProperty 速度快很多。
無論如何,Common Configuration 是一個非常優秀的 java 工具包。我注意到,在它的開發 roadmap 中,INI 格式配置計劃在 1.3 版本中支援,應該說 INI 格式不難,不知道為什麼要放到 1.3 版本中才能實現。1.3 版本還計劃支援 windows 註冊表格式的配置,個人覺得沒有什麼大的用處。其他有些稀奇古怪的計劃,可能是有的開發人員提出的不太通用的一些要求。從目前的開發版本的 bugzilla 上面看,沒有較核心的 bug ,比較讓人放心,值得推薦。