在軟件開發和部署過程當中,咱們的軟件每每須要在不一樣的運行環境中運行,例如:開發人員本地開發環境、測試團隊的測試環境、生產仿真環境、正式生產環境,不一樣的公司可能還會有更多的環境須要對項目配置進行動態切換。項目在這些環境切換的過程當中,每每會有一部分配置是全部的環境都相同的,還有一部分是不一樣環境都不相同的(最典型的就是數據鏈接配置文件jdbc.properties),若是咱們不作特殊配置,那麼咱們就須要根據環境來修改配置文件,不一樣環境來回修改和切換,不只容易出錯,並且很繁瑣,那麼這時候咱們在想:有沒有辦法能夠可以讓咱們不用修改配置就能發佈到不一樣的環境中呢?答案顯而易見,那麼本文咱們就經過三種方式來解決這個問題。從而把咱們的軟件的可移植性提升一個層次。java
Spring 4.2.6.RELEASEgit
SpringMvc 4.2.6.RELEASEgithub
Mybatis 3.2.8web
Maven 3.3.9spring
Jdk 1.7數據庫
Idea 15.04tomcat
首先咱們在spring-dao.xml有以下數據源定義:jvm
<!-- 配置數據源,數據庫鏈接池 --> <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、數據庫用戶名、數據庫密碼等.jsp
1.在spring.xml中的數據源配置以前定義不一樣的spring的profilemaven
<!-- 開發環境配置 --> <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>
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包
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參數替換配置文件內容。我我的更傾向於和推薦使用第二種方式,它靈活多變,可擴展性高!