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

简介: 一、背景       在软件开发和部署过程中,我们的软件往往需要在不同的运行环境中运行,例如:开发人员本地开发环境、测试团队的测试环境、生产仿真环境、正式生产环境,不同的公司可能还会有更多的环境需要对项目配置进行动态切换。

一、背景   

   在软件开发和部署过程中,我们的软件往往需要在不同的运行环境中运行,例如:开发人员本地开发环境、测试团队的测试环境、生产仿真环境、正式生产环境,不同的公司可能还会有更多的环境需要对项目配置进行动态切换。项目在这些环境切换的过程中,往往会有一部分配置是所有的环境都相同的,还有一部分是不同环境都不相同的(最典型的就是数据连接配置文件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.不同环境构建或者打包项目

  所有的上述步骤昨晚以后,见证奇迹的时候到了,我们只需要在运行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参数替换配置文件内容。我个人更倾向于和推荐使用第二种方式,它灵活多变,可扩展性高!

相关文章
|
Java 应用服务中间件 微服务
信创迁移适配实战-SpringBoot项目打包war部署至TongWeb7
信创迁移适配实战-SpringBoot项目打包war部署至TongWeb7
3729 0
信创迁移适配实战-SpringBoot项目打包war部署至TongWeb7
|
2月前
|
jenkins Java 持续交付
Jenkins打包,发布,部署
Jenkins打包,发布,部署
240 0
|
3月前
|
jenkins 持续交付 Docker
自动化部署:从源代码到生产环境
在这篇文章中,我们将一起探索如何将代码从源代码库自动部署到生产环境。我们将通过一个简单的Python Flask应用示例,展示如何使用Docker和Jenkins实现自动化部署。在这个过程中,我们将学习如何编写Dockerfile,创建Jenkins任务,以及如何将这两个工具结合起来实现自动化部署。无论你是运维新手还是经验丰富的老手,这篇文章都将为你提供有价值的参考。【8月更文挑战第31天】
|
6月前
|
运维 安全 Java
SpringBoot运维篇(打包,多环境,日志)
SpringBoot运维篇(打包,多环境,日志)
|
7月前
|
Java 应用服务中间件 持续交付
项目打包、部署
项目打包、部署【2月更文挑战第16天】
68 6
|
Java 应用服务中间件 Linux
7、SpringBoot2.0如何打包部署上线(七)
1、打包一般分为两种;一种是打包成jar包直接执行,另一种是打包成war包放到tomcat服务器下。
170 0
7、SpringBoot2.0如何打包部署上线(七)
|
Java 应用服务中间件 Maven
|
测试技术 Swift iOS开发
iOS开发 - 一个工程多环境切换,适合需要经常打很多不同环境包的人
iOS开发 - 一个工程多环境切换,适合需要经常打很多不同环境包的人
345 0
iOS开发 - 一个工程多环境切换,适合需要经常打很多不同环境包的人
vite配置多环境打包
vite配置多环境打包
1534 0
vite配置多环境打包