對於java程序員來說各種各樣的配置文件是司空見慣的,比如spring的bean配置,struts的action配置等等。有些配置會隨着運行環境的變化而各不相同,最典型的就是jdbc驅動的配置,在開發環境可能鏈接到開發本地的數據庫,測試環境則有一套測試專用的數據庫環境,線上的生產環境也會有一套數據庫,如果一個應用要部署到多個idc中,那這些配置又有可能各不相同。解決這個問題,可能有些團隊使用同一份配置文件,在部署到不同的環境之前人肉的修改一下配置,還有些團隊會為每一個環境維護一份配置文件。這些做法都比較容易出錯,而且隨着環境的增多成本會線性地增長。
本文通過一個示例簡單介紹一個自動化的配置工具autoconfig。autoconfig使用一套配置模板,為不同的環境生成相應的具體配置。它的核心思想是把一些可變的配置定義為一個模板,在autoconfig運行的時候從這些模板中生成具體的配置文件。autoconfig支持兩種運行方式,第一種是作為普通的java應用程序從命令行來調用,另一種是作為maven的插件來運行。本文通過一個maven項目展示一下如何在maven中使用autoconfig。
autoconfig是一個淘寶開源的web框架webx的一個工具包,svn地址為 http://code.taobao.org/svn/webx/citrus-tool/trunk/,使用之前先checkout源代碼本地安裝一下,當然感興趣的同學也可已研究一下它的源代碼。安裝非常簡單,在checkout的源代碼的根目錄下運行 mvn clean install -Dmaven.test.skip。由於autoconfig使用maven build,安裝之前必須先安裝maven,不知到如何安裝maven的同學可以google一下。
創建antoconfig的描述文件auto-config.xml以及配置文件config.properties的模板config.properties.vm。
config.properties的模板內容如下,它只有一行配置。
key = ${net_kiminotes_value}
antoconfig的描述文件auto-config.xml內容如下。
<config>
<group>
<property name="net.kiminotes.value" />
</group>
<script>
<generate template="config.properties.vm" destfile="config.properties" charset="utf-8" />
</script>
</config>
property元素定義了一個需要autoconfig配置的屬性 net.kiminotes.value。group元素把不同類庫的property進行分組,這里僅配置了一個group。generate定義了一個配置文件生成策略,template屬性定義了配置文件的的模板,destfile定義了生成后配置文件的存放位置。
注: 有人或許會感覺迷惑,在模板文件config.properties.vm中,需要被替換的明明是net_kiminotes_value,為什么在auto-config.xml文件中會定義屬性 net.kiminotes.value 呢?現在只需要記住屬性名中的點在autoconfig執行的時候會被替換成下划線,具體原因會在后續的blog中解釋。
最后在pom中配置一下maven autoconfig插件,整個pom文件如下。
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>net.kiminotes</groupId> <artifactId>autoconfig</artifactId> <version>1.0-SNAPSHOT</version> <packaging>jar</packaging> <build> <plugins> <plugin> <groupId>com.alibaba.citrus.tool</groupId> <artifactId>maven-autoconfig-plugin</artifactId> <version>1.0.9</version> <executions> <!-- 配置在package phase中運行maven-autoconfig-plugin的autoconfig goal --> <execution> <id>config</id> <goals> <goal>autoconfig</goal> </goals> <phase>package</phase> </execution> </executions> </plugin> <plugin> <artifactId>maven-jar-plugin</artifactId> <configuration> <archive> <!-- 打出的jar包中的 MANIFEST.MF 文件中增加 Main-Class 這一項配置,這樣就能在命令行中通過 java -jar 來執行打出的jar包 --> <manifestEntries> <Main-Class>net.kiminotes.Main</Main-Class> </manifestEntries> </archive> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>2.3.2</version> <configuration> <target>1.6</target> <source>1.6</source> </configuration> </plugin> </plugins> </build> </project>
在配置文件的模板 config.properties.vm 中有一個配置變量 ${net_kiminotes_value} 在執行autoconfig的時候需要被替換,那怎么給這個配置項賦值呢?autoconfig提供了兩種方式來給配置變量賦值第一從java屬性文件中讀取第二是交互式地編輯。autoconfig首先讀取當前工作目錄的antx.properties文件,如果沒有則讀取${user.home}/antx.properties文件,如果這個文件也不存在,autoconfig就會啟動交互式編輯器請求用戶輸入配置變量的值,如果配置變量的值是不完整的autoconfig則會立即停止配置並拋出一個異常。如果java屬性文件的位置不在autoconfig默認的位置可以通過參數autoconfig.userProperties進行配置。處於簡單其間,我們在當前目錄新建一個java屬性文件antx.properties,這個文件中定義了配置變量${net_kiminotes_value}的值。antx.properties 文件的內容如下。
net.kiminotes.value = hello, world
整個項目的結構如下所示:

下面運行maven來build這個項目。運行 mvn package,在target目錄下生成一個jar包autoconfig-1.0-SNAPSHOT.jar,運行這個jar包。

