13 10月 2010

Maven2 : Portable Configuration

最近Support中x信托個金的WebATM案子,非常訝異,SCM checkout出來的source code不能compile,四個環境上跑的是哪個版本也不能確定,環境上的configuration也都不能完全確定哪個是正確的,再來改版時的patch是一個個class複製到deployment目錄下,XML或Properties也都是手動一個個修改....拜託,什麼年代了!?

能用程式做的就不要手動,寫個maven或ant的設定有這麼麻煩嗎?時間要花在更有義意的事情上,減少手動的工作,也減少人為的錯誤,多出來的時間回去陪家人不是更好些嗎....

XML及Properties的變動不外乎兩種方式解決
(1)Merge : 在範本檔案以${變數名}做為標記,然後再為不同環境寫不同的設定檔,為每個變數定出符合該環境的值,在Build的時候將範本與變數檔進行Merge,產生該環境專用的檔案,該檔案應與範本檔案同名
(2)Replace:為不同環境另存不同名的檔案,在Build的時以更名覆蓋的方式產生該環境專用的檔案

Merge的變數值有幾種設定方式
(1)放在系統變數中,範本檔以${env.變數名}取得該值,例如 export profilename=ABC;
(2)放在java 啟動參數數,以 -D變數名=變數值 帶入,範本檔則以${變數名}取得該值,例如 mvn -Dprofilename=ABC
(3)放在pom.xml中,以<properties><變數名>變數值</變數名></properties>設定,範本檔則以${變數名}取得該值,各profile可以自訂不同的properties
(4)放在其他檔案中,以一般java的properties檔案格式設定,如 變數名=變數值,在pom.xml中以<filters><filter>變數值設定檔</filter></filters>,範本檔則以${變數名}取得該值。

簡單看一下Maven的例子,下圖是一個非常簡單的maven project

其中
conf/prod/env.properties是prod環境Merge用的變數值設定檔案

setting.envname=prod

conf/template/system.properties則是上列所提Merge用的範本檔

profile.name=${profilename} #取自pom.xml中的設定
package.envname=${setting.envname} #取自env.properties
M2=${env.M2_HOME} #取自系統變數

src/main/resource下的兩個檔案則是為了展示利用antrun來執行Replace的操作,裡面的內容隨便設定,只要不一樣即可

再來列出pom.xml中的profiles設定

<profiles>
    <profile>
        <id>prod</id>
        <!-- 在Maven內自訂變數值 -->
        <properties>
            <profilename>PROD</profilename>
        </properties>
        <build>
        <!-- 將變數訂在特定檔案(env.properties) -->
            <filters>
                <filter>${basedir}/conf/prod/env.properties</filter>
            </filters>
            <resources>
                <!-- 系統原用的resource -->
                <resource>
                    <directory>${basedir}/src/main/resources</directory>
                </resource>
    <!-- 因不同環境會有變動的設定檔範本 -->
    <resource>
        <directory>${basedir}/conf/template</directory>
        <filtering>true</filtering>
                </resource>
            </resources>
            <plugins>
            <!-- 利用Ant Run的Copy來取代檔案 -->
                <plugin>
                    <artifactid>maven-antrun-plugin</artifactid>
                    <executions>
                        <execution>
                            <phase>process-resources</phase>
                            <goals>
        <goal>run</goal>
                </goals>
                <configuration>
        <tasks>
            <delete file="${project.build.outputDirectory}/antrun.replace">
            </delete><copy tofile="${project.build.outputDirectory}/antrun.replace" file="${basedir}/src/main/resources/antrun.replace.prod">
        </copy></tasks>
                </configuration>
            </execution>
        </executions>
    </plugin>
            </plugins>
        </build>
    </profile>
</profiles>
</profiles>

再執行 mvn package -Pprod就可以看到結果了


沒有留言: