Maven下實現多種環境下的資源配置管理

構建項目時可能會遇到在測試(如單元測試)、開發、模擬、生產等不同環境下需要不同配置(properties、xml)或資源(jpg、png、mp3)的情況。比如常見的數據庫連接(即 jdbc url)的值,在不同的環境下可能有如下幾種值:

  • 測試環境:jdbc:mysql://localhost:3306/foobar_test
  • 開發環境:jdbc:mysql://localhost:3306/foobar_dev
  • 模擬環境:jdbc:mysql://192.168.1.11:3306/foobar
  • 生產環境:jdbc:mysql://192.168.1.10:3306/foobar

或者同樣是生產環境,針對(產品)交付給A公司客戶的與交付給B公司客戶的需要不同配置或者資源,比如產品界面中的公司名稱、公司LOGO等。

又或者針對不同的操作系統(如 Windows,Linux)需要爲某個配置設定不同的文件路徑。

可見,在不同的軟件開發生命週期階段、不同的最終客戶(用戶)環境、不同的運行平臺都有可能需要不同配置或資源的情況。假如各個環境下的差別很小的話,我們可以在項目編譯之後手工修改或者寫個 shell script 自動修改,但如果需要修改的項目很多而且複雜的話,則應該使用 Apache Maven來管理。

 

有兩種實現方式,

    第一種類似項目中使用的,定義三個文件:

        src/main/resources/config_DEV.properties

        src/main/resources/config_TEST.properties

        src/main/resources/config_PROD.properties

    項目中實際引用的是config.properties,通過maven-antrun-plugin來實現替換

    (ps:config.properties 文件不需要提前創建,編譯時自動copy)

 

    第二種方式利用了maven的profile和filtering的功能,把上述步驟的直接替換改爲過濾器來進行選擇。缺點是,如果在其它配置文件中引用變量還可以,如果在java文件中讀取需要指定文件名時還需要額外做判斷,不靈活。

配置文件引用:
<bean id="uploadService" class="com.oist.project.service.UploadServiceImpl">
    <property name="uploadDir" value="${spring.uploadDir}"/>
  </bean>

   

原理可參考鏈接:

       http://archboy.org/2012/05/21/apache-maven-profile-filtering-multiple-build-environments/

    具體實現最好參考:

         http://blog.csdn.net/wangjunjun2008/article/details/11516323

        http://blog.csdn.net/wuxinzaiyu/article/details/8524274

        http://blog.csdn.net/crazycoder2010/article/details/7264644

 

  1. <build>  
  2.         <filters>  
  3.             <filter>src/main/resources/config_${env}.properties</filter>   //要過濾的文件路徑、名稱
  4.         </filters>  
  5.         <resources>  
  6.             <resource>  
  7.                 <directory>src/main/resources</directory>  //這個路徑下的文件打開過濾
  8.                 <filtering>true</filtering>  
  9.             </resource>  
  10.         </resources>  
  11.   
  12.         ......  
  13.   
  14.     </build> 

這種方式需要提前創建好config.properties文件,且文件內容格式爲:

jdbc.driverClassName=${jdbc.driverClassName}

jdbc.url=${jdbc.url}

jdbc.username=${jdbc.username}

jdbc.password=${jdbc.password}

編譯後,佔位符中內容將會被替換爲實際值

 

    省事的方式是直接將屬性定義在profile裏,其它地方直接引用,變量多時比較臃腫,不建議

        <profile>

            <id>dev</id>

            <activation>

                <activeByDefault>true</activeByDefault>

            </activation>

            <properties>

                <redis.hostName>cache01.game.sogou-inc.com</redis.hostName>

                <redis.port>6380</redis.port>

                <jdbc.driver>com.p6spy.engine.spy.P6SpyDriver</jdbc.driver>

                <!--<jdbc.driver>com.mysql.jdbc.Driver</jdbc.driver>-->

                <logback.logLevel>debug</logback.logLevel>

                <static.resource>http://localhost</static.resource>

                <ime.push.online>false</ime.push.online>

            </properties>

        </profile>

在編譯項目時,可以使用 -P 參數指定需要使用的 profile 的 id,比如下面命令將會使用 dev profile:

$mvn clean compile -Pdev
假如不指定 -P 參數的話,則會使用 activeByDefault=true 的一項

 如果代碼中需要判斷當前環境,一般通過獲取本機ip地址做判斷

 

還有第三種方式更簡單,利用resin properties重寫的功能,避免環境依賴,開發機、測試機、預發佈機、線上機容器中分別配置對應的屬性。

<context:property-placeholder order="0" location="classpath:app.properties"  system-properties-mode="OVERRIDE"/>

 

在resin配置文件/usr/local/resin/conf/resin.xml 中去配置app.properties中的參數

    <!-- Java system-properties -->

    <system-property mail.smtp.host="127.0.0.1"/>

    <system-property mail.smtp.port="25"/>

    <system-property spring.profiles.active="production"/>

 

    <system-property domain="api.app.wan.sogou.com"/>

 

    <system-property peak.api_server="http://up.sohu.com"/>

    <system-property peak.pub_server="https://up.sohu.com"/>

    <system-property peak.game_center_callback="http://api.app.wan.sogou.com/api/peak.do"/>

 

    <system-property midas.api_host="api.unipay.qq.com"/>

 

    <system-property db.game.host="mblgm01.dt.mysql.db"/>

    <system-property db.game.user="shouyou"/>

    <system-property db.game.password="shouyou!@#$"/>

 

    <system-property memcached.servers="10.11.211.101:11211"/>

 

    <system-property redis.host="redis01.shouyou.tc.vm"/>

 

    <system-property redis.port="6379"/>

 

外部配置

有時候有些關鍵的屬性,比如數據庫密碼,需要放在xml文件之外,便於後續修改。Spring解決這個問題的方法有兩種,一種是屬性佔位符,一種是屬性重寫。另外阿里提供的AutoConfig有更好的配置管理機制,將在後面詳細介紹。

 

第一種:關於佔位符,首先載入屬性文件:

  1. <context:property-placeholder location="classpath:/db.properties"/>  
  2. 或者  
  3. <context:property-placeholder location="file:///etc/db.properties"/>  

 

引用屬性中的變量:

  1. <bean id="dataSource" class="org.springframework.jdbc.datbase.DriverManagerDataSource">  
  2.   <property name="driverClassName" value="${jdbc.driverClassName}"/>  
  3.   <property name="url" value="${jdbc.url}/>  
  4. </bean>  

 

第二種:

(1)覆蓋properties文件中的變量:

  1. <util:properties id="defConf>  
  2.   <prop key="jdbc.url">jdbc:mysql://localhost/test</prop>  
  3.   <prop key="jdbc.driverClassName">com.mysql.jdbc.Driver</prop>  
  4. </util:properties>  
  5.   
  6. <context:property-placeholder location="classpath:/db.properties" properties-ref="defConf" 
  7.     system-properties-mode="OVERRIDE"/>  
  8. 除了OVERRIDE還有FALLBACK、NEVER。  

這個就是上面的例子,通過resin配置文件修改了system properties。

 

 

(2) 覆蓋xml配置。載入properties文件並覆蓋現有的xml配置。請看下面的例子:

  1. <bean id="dataSource" class="xxx">  
  2.   <property name="url">jdbc:oracle://xxx</property>  
  3.   <property name="username">xxx</property>  
  4. </bean>  
  5.   
  6. <context:property-overrider location="classpath:/db.properties"/>  

這個用另一個文件替換了原來的文件

 

System Properties

In Properties, we examined the way an application can use Properties objects to maintain its configuration. The Java platform itself uses a Properties object to maintain its own configuration. The System class maintains a Properties object that describes the configuration of the current working environment. System properties include information about the current user, the current version of the Java runtime, and the character used to separate components of a file path name.

 

The following table describes some of the most important system properties

Key Meaning
   
"java.class.path" Path used to find directories and JAR archives containing class files. Elements of the class path are separated by a platform-specific character specified in the path.separator property.
"java.home" Installation directory for Java Runtime Environment (JRE)

 

Resin 中

<system-property>

child of resin,cluster,host,web-app

Sets a Java system property. The effect is the same as if you had called before starting Resin.

Example: setting system property
 
<resin>
  <system-property foo="bar"/>
</resin>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章