原来实现项目多环境打包部署是如此的简单

1、背景   

   在软件开发和部署过程当中,咱们的软件每每须要在不一样的运行环境中运行,例如:开发人员本地开发环境、测试团队的测试环境、生产仿真环境、正式生产环境,不一样的公司可能还会有更多的环境须要对项目配置进行动态切换。项目在这些环境切换的过程当中,每每会有一部分配置是全部的环境都相同的,还有一部分是不一样环境都不相同的(最典型的就是数据链接配置文件jdbc.properties),若是咱们不作特殊配置,那么咱们就须要根据环境来修改配置文件,不一样环境来回修改和切换,不只容易出错,并且很繁琐,那么这时候咱们在想:有没有办法能够可以让咱们不用修改配置就能发布到不一样的环境中呢?答案显而易见,那么本文咱们就经过三种方式来解决这个问题。从而把咱们的软件的可移植性提升一个层次。java

2、软件环境

  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

3、方式一:使用spring的profile机制实现

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> 

4、方式二:使用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包

5、方式三:使用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

6、总结

  三种方式均可以很完美的实现多环境打包部署,但方式一依赖spring,方式二和方式三依赖maven。第二种方式是运行时替换占位符,可使用JVM参数来替换配置文件内容,第三种方式是打包时替换占位符,不支持运行时经过JVM参数替换配置文件内容。我我的更倾向于和推荐使用第二种方式,它灵活多变,可扩展性高!

相关文章
相关标签/搜索