1. 程式人生 > >通過 spring 容器內建的 profile 功能實現開發環境、測試環境、生產環境配置自動切換

通過 spring 容器內建的 profile 功能實現開發環境、測試環境、生產環境配置自動切換

軟體開發的一般流程為工程師開發 -> 測試 -> 上線,因此就涉及到三個不同的環境,開發環境、測試環境以及生產環境,通常這三個環境會有很多配置引數不同,例如資料來源、檔案路徑、url等,如果每次上線一個新版本時都手動修改配置會十分繁瑣,容易出錯。spring 為我們提供了 profile 機制來解決這個問題。


spring允許我們通過定義 profile 來將若干不同的 bean 定義組織起來,從而實現不同環境自動啟用不同的 profile 來切換配置引數的功能,下面介紹以 xml 的方式定義 profile、如何啟用 profile以及定義預設的 profile,整個過程我以配置不同環境的資料來源為例,為了簡化配置,這裡假設只有開發和生產兩個環境。


資料來源定義為
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
    <property name="user" value="${jdbc.user}" /> 
    <property name="password" value="${jdbc.password}" /> 
    <property name="jdbcUrl" value="${jdbc.jdbcUrl}" />   
    <property name="driverClass" value="${jdbc.driverClass}" />
    <property name="initialPoolSize" value="${c3p0.initialPoolSize}"/>
    <property name="acquireIncrement" value="${c3p0.acquireIncrement}"/>
    <property name="minPoolSize" value="${c3p0.minPoolSize}"/>
    <property name="maxIdleTime" value="${c3p0.maxIdleTime}"/>
    <property name="idleConnectionTestPeriod" value="${c3p0.idleConnectionTestPeriod}" />
    <property name="preferredTestQuery" value="${c3p0.preferredTestQuery}"/>
</bean>



classpath下外部資原始檔有兩個 settings-development.properties 和 settings-production.properties,分別是開發環境和生產環境的資料來源配置引數,內容如下


settings-development.properties
jdbc.user=root
jdbc.password=111111
jdbc.driverClass=com.mysql.jdbc.Driver
jdbc.jdbcUrl=jdbc:mysql://localhost:3306/xxx
c3p0.minPoolSize=5 
c3p0.initialPoolSize=5
c3p0.acquireIncrement=5
c3p0.maxIdleTime=3600
c3p0.idleConnectionTestPeriod=3600
c3p0.preferredTestQuery=select 1



settings-production.properties
jdbc.user=xxx
jdbc.password=xxxx
jdbc.driverClass=com.mysql.jdbc.Driver
jdbc.jdbcUrl=jdbc:mysql:///xxx
c3p0.minPoolSize=20 
c3p0.initialPoolSize=20
c3p0.acquireIncrement=10
c3p0.maxIdleTime=3600
c3p0.idleConnectionTestPeriod=3600
c3p0.preferredTestQuery=select 1





1. 定義 profile


現在就可以通過定義 profile 來將開發和生產環境的資料來源配置分開,這裡我們定義兩個 profile,一個名稱是 development,另一個名稱是 production
<!-- 開發環境配置檔案 -->
<beans profile="development">
    <context:property-placeholder location="classpath:settings-development.properties"/>
</beans>
 
<!-- 生產環境配置檔案 -->
<beans profile="production">
    <context:property-placeholder location="classpath:settings-production.properties"/>
</beans>





2. 定義預設 profile


預設 profile 是指在沒有任何 profile 被啟用的情況下,預設 profile 內定義的內容將被使用,通常可以在 web.xml 中定義全域性 servlet 上下文引數 spring.profiles.default 實現,程式碼如下

<!-- 配置spring的預設profile -->
<context-param>
    <param-name>spring.profiles.default</param-name>
    <param-value>development</param-value>
</context-param>




3. 啟用 profile 


spring 為我們提供了大量的啟用 profile 的方法,可以通過程式碼來啟用,也可以通過系統環境變數、JVM引數、servlet上下文引數來定義 spring.profiles.active 引數啟用 profile,這裡我們通過定義 JVM 引數實現。
在生產環境中,以 tomcat 為例,我們在 tomcat 的啟動指令碼中加入以下 JVM 引數

-Dspring.profiles.active="production"


而開發環境中不需要定義該引數,如果不定義,則會使用我們指定的預設 profile ,在這裡也就是名稱為 development 的 profile。這樣當專案部署到不同的環境時,便可以通過 JVM 引數來實現不同環境 profile 自動啟用。


4. 延伸


該引數還可以延伸,以至於我們可以在 java 程式碼中繼續通過該引數來區分不同的環境,從而執行不同的操作,程式碼如下

public class Config {
      public static String ENV = "development";
}
public class InitConfigListener implements ServletContextListener {
    public void contextInitialized(ServletContextEvent sce) {
        //偵測jvm環境,並快取到全域性變數中
        String env = System.getProperty("spring.profiles.active");
        if(env == null) {
            Config.ENV = "development";
        } else {
            Config.ENV = env;
        }
    }
}
在專案初始化時獲取到該引數後,我們便可以在專案任何位置使用,來執行一些不同環境需要區別對待的操作,例如統計流量的程式碼只需要在生產環境啟用,就可以在jsp中加入如下程式碼

<!-- 生產環境統計、推送程式碼 -->
<c:if test="${env == 'production' }">
<script>
//統計程式碼
..
</script>
</c:if>