原來實現項目多環境打包部署是如此的簡單


一、背景   

   在軟件開發和部署過程中,我們的軟件往往需要在不同的運行環境中運行,例如:開發人員本地開發環境、測試團隊的測試環境、生產仿真環境、正式生產環境,不同的公司可能還會有更多的環境需要對項目配置進行動態切換。項目在這些環境切換的過程中,往往會有一部分配置是所有的環境都相同的,還有一部分是不同環境都不相同的(最典型的就是數據連接配置文件jdbc.properties),如果我們不做特殊配置,那么我們就需要根據環境來修改配置文件,不同環境來回修改和切換,不僅容易出錯,而且很繁瑣,那么這時候我們在想:有沒有辦法可以能夠讓我們不用修改配置就能發布到不同的環境中呢?答案顯而易見,那么本文我們就通過三種方式來解決這個問題。從而把我們的軟件的可移植性提高一個層次。

二、軟件環境

  Spring 4.2.6.RELEASE

  SpringMvc 4.2.6.RELEASE

  Mybatis 3.2.8

  Maven 3.3.9

  Jdk 1.7

  Idea 15.04

首先我們在spring-dao.xml有如下數據源定義:

<!-- 配置數據源,數據庫連接池 -->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close">
    <!--數據庫驅動-->
    <property name="driverClassName" value="${jdbc.driver}"/>
    <!--數據庫鏈接地址-->
    <property name="url" value="${jdbc.url}"/>
    <!--數據庫用戶名-->
    <property name="username" value="${jdbc.username}"/>
    <!--數據庫連接密碼-->
    <property name="password" value="${jdbc.password}"/>
    <!--連接池初始化大小-->
    <property name="initialSize" value="${jdbc.initialSize}"/>
    <!--連接池最小數量-->
    <property name="minIdle" value="${jdbc.minIdle}" />
    <!--連接池最大數量-->
    <property name="maxActive" value="${jdbc.maxActive}"/>
    <!--連接池等待超時時間-->
    <property name="maxWait" value="${jdbc.maxWait}"/>
    <!--配置間隔多久才進行一次檢測,檢測需要關閉空閑連接,單位是毫秒-->
    <property name="timeBetweenEvictionRunsMillis" value="${jdbc.timeBetweenEvictionRunsMillis}"/>
    <property name="minEvictableIdleTimeMillis" value="${jdbc.minEvictableIdleTimeMillis}"/>
    <property name="testWhileIdle" value="${jdbc.testWhileIdle}"/>
    <property name="validationQuery" value="${jdbc.validationQuery}"/>
    <property name="testOnReturn" value="${jdbc.testOnReturn}"/>
    <!--打開PSCache,並且制定每個連接上PSCache的大小-->
    <property name="poolPreparedStatements" value="${jdbc.poolPreparedStatements}"/>
    <property name="maxPoolPreparedStatementPerConnectionSize" value="${jdbc.maxPoolPreparedStatementPerConnectionSize}"/>
    <!--配置監控統計攔截的filters-->
    <property name="filters" value="${jdbc.filters}"/>
</bean>

然后,我們在classpath的config文件夾下定義:config-development.properties、config-test.properties、config-emulation.properties、config-production.properties四個分別對應本地開發環境、測試環境、仿真環境、生產環境的配置文件,它們中分別指定着不同的配置參數,如數據庫連接url、數據庫用戶名、數據庫密碼等.

三、方式一:使用spring的profile機制實現

1.在spring.xml中的數據源配置之前定義不同的spring的profile

<!-- 開發環境配置 -->
<beans profile="dev">
    <context:property-placeholder location="classpath:config/config-development.properties"/>
</beans>
        <!-- 測試環境配置 -->
<beans profile="test">
<context:property-placeholder location="classpath:config/config-test.properties"/>
</beans>
        <!-- 仿真環境配置 -->
<beans profile="emu">
<context:property-placeholder location="classpath:config/config-emulation.properties"/>
</beans>
        <!-- 生產環境配置 -->
<beans profile="prod">
<context:property-placeholder location="classpath:config/config-production.properties"/>
</beans>
        <!--其他和環境無關的配置-->
<beans>
.....
</beans>

然后spring.xml中和環境無關的配置用一個不設置profile的beans標簽包裹。

2.定義默認生效的profile,也就是當我們沒有主動激活任何profile的情況下,該配置會生效.

  1).web.xml中進行如下設置

<!-- 配置spring的默認profile -->  
<context-param>  
    <param-name>spring.profiles.default</param-name>  
       <param-value>dev</param-value>  
</context-param>

  2).在spring-dao.xml指定默認profile

<beans profile="default">  
    <context:property-placeholder location="classpath:config/config-development.properties"/>  
</beans> 

3.多環境切換方式

  spring為我們提供了大量的激活profile的方式:代碼激活、系統環境變量激活、JVM參數激活、Servlet上下文參數激動等。我們一般用的最多的就是使用JVM參數進行激活,簡單方便。以tomcat為例,我們只需要在tomcat的啟動腳本中加入以下JVM參數:-Dspring.profiles.active=xxx (其中xxx為我們在spring-dao.xml中定義的profile的名稱:dev、test、emu、prod),在不同的環境中我們指定該參數的值為環境對應的profile名稱即可。很靈活,代碼也不需要做出任何改變。

4.使用擴展

spring的profile還允許我們在java代碼或者jsp的el表達式中來根據該參數做不同的操作。如:

public void test() {  
    //偵測jvm環境
    String env = System.getProperty("spring.profiles.active");  
    if(env == "dev") {  
        do xxx;  
    } else {  
        do other things;  
    }  
}

在jsp的el表達式中使用,比如我們只需要在生產環境添加統計流量的代碼等:

<!-- 生產環境統計、推送代碼 -->  
<c:if test="${spring.profiles.active == 'prod' }">  
<script>  
//統計代碼  
..  
</script>  
</c:if> 

四、方式二:使用maven的profile機制實現

1.在項目的pom.xml中定義maven profiles

<profiles>
    <profile>
        <!-- 本地開發環境 -->
        <id>dev</id>
        <properties>
            <environment>development</environment>
        </properties>
        <activation>
            <activeByDefault>true</activeByDefault>
        </activation>
    </profile>
    <profile>
        <!-- 測試環境 -->
        <id>test</id>
        <properties>
            <environment>test</environment>
        </properties>
    </profile>
    <profile>
        <!-- 仿真環境 -->
        <id>emu</id>
        <properties>
            <environment>emulation</environment>
        </properties>
    </profile>
    <profile>
        <!-- 生產環境 -->
        <id>prod</id>
        <properties>
            <environment>production</environment>
        </properties>
    </profile>
</profiles>

這里我們定義了四個環境,分別為:development(開發環境)、test(測試環境)、emulation(仿真環境)、production(生產環境),其中開發環境模式是激活的(activeByDefault為true),這樣如果我們在不指定profile的情況下默認是開發環境。

2.在spring-dao.xml中進行如下配置:

<context:property-placeholder location="classpath:config/config-${environment}.properties"/>

3.接着在pom.xml中定義resources中要被過濾的資源

<build>
    <resources>
        <resource>
        <directory>src/main/resources</directory>
        <filtering>true</filtering>
        </resource>
    </resources>
</build>

4.不同環境構建或者打包項目

  所有的上述步驟昨晚以后,見證奇跡的時候到了,我們只需要在運行maven命令的時候指定使用不同的profile名稱就可以實現構建或發布到不同環境需要的war包,如:

  mvn clean package -Pprod 即構建出生產環境需要的war包

  mvn clean install -Ptest 即構建要發布到測試環境的war包

五、方式三:使用maven的profile + resources + filter實現

1.首先和第二種方式一樣在pom.xml中進行如下配置各個環境對應的profiles

<profiles>
    <profile>
        <id>dev</id>
        <properties>
            <environment>development</environment>
        </properties>
        <activation>
            <activeByDefault>true</activeByDefault>
        </activation>
    </profile>
    <profile>
        <id>test</id>
        <properties>
            <environment>test</environment>
        </properties>
    </profile>
    <profile>
        <id>emu</id>
        <properties>
            <environment>emulation</environment>
        </properties>
    </profile>
    <profile>
        <id>prod</id>
        <properties>
            <environment>production</environment>
        </properties>
    </profile>
</profiles>

2.接着在pom.xml中定義resources中要被過濾的資源以及過濾時用到的資源文件

<build>
    <resources>
        <resource>
            <directory>src/main/resources</directory>
            <excludes>
                <exclude>config/*</exclude>
            </excludes>
            <filtering>true</filtering>
        </resource>
        <resource>
            <directory>src/main/resources</directory>
            <includes>
                <include>config/config-${environment}.properties</include>
            </includes>
            <filtering>false</filtering>
        </resource>
    </resources>
    <filters>
        <filter>src/main/resources/config/config-${environment}.properties</filter>
    </filters>
</build>

  注:上面配置中第一個resource定義了排除config文件夾下的所有文件,並且對src/main/resources文件夾進行過濾替換占位符,使用的配置文件是紅色部分標出的文件,第二個resource定義了將config文件夾下config-${environment}.properties文件作為資源文件,並且不對該文件做過濾。

3.不同環境構建或者打包項目

  我們只需要在運行maven命令的時候指定使用不同的profile名稱就可以實現構建或發布到不同環境需要的war包,如:

    mvn clean package -Pprod 即構建出生產環境需要的war包
    mvn clean install -Ptest 即構建要發布到測試環境的war包

項目github地址:https://github.com/hafizzhang/maven-profile.git

六、總結

  三種方式都可以很完美的實現多環境打包部署,但方式一依賴spring,方式二和方式三依賴maven。第二種方式是運行時替換占位符,可以使用JVM參數來替換配置文件內容,第三種方式是打包時替換占位符,不支持運行時通過JVM參數替換配置文件內容。我個人更傾向於和推薦使用第二種方式,它靈活多變,可擴展性高!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM