在大型的项目组中,分不同的开发环境,测试环境,生产环境(说白了就是配置文件不同,或者数据源,或者服务器,或者数据库等);问题来了,如何使用Maven针对不同的环境来打包呢?

Maven提供了Profile的概念,用来解决此类问题,其原理很简单,就是使用变量替换;举个例子来说明,测试项目目录结构如下图所示:

比如开发环境和生产环境的数据库不同,db.properties配置文件内容如下:

#测试库
db.url=192.10.2.168
db.username=dbtest
db.password=dbtest
#正式库
#db.url=192.20.1.11
#db.username=admin
#db.password=comfreesecurity

生产环境打包时,需要手动修改该配置文件;juvenxu说过,手动意味着低效率,高错误率!!

使用Profile时,以上情况可简化如下:

1、在pom.xml文件中定义两个不同的Profile,分别定义开发环境和生产环境的数据库信息:

<profiles>
<profile>
<id>kaifa</id>
<properties>
<db.url>192.10.2.168</db.url>
<db.username>dbtest</db.username>
<db.password>dbtest</db.password>
</properties>
</profile> <profile>
<id>shengchan</id>
<properties>
<db.url>192.20.1.11</db.url>
<db.username>admin</db.username>
<db.password>comfreesecurity</db.password>
</properties>
</profile>
</profiles>

2、将原来的配置文件内容修改如下:

db.url=${db.url}
db.username=${db.username}
db.password=${db.password}

3、需要开启资源文件过滤,代码如下:

<resources>
<resource>
<directory>${project.basedir}/src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>

添加<filtering>true</filtering>,允许使用变量替换资源文件;
4、使用Maven命令打包时,指定Profile进行打包,命令如下:

mvn package -Pkaifa

mvn package -Pshengchan

如此即可。

此命令用的多了,就会发现,两个环境必选其一,如果能设置其一个为默认开启,就不用每次都手动指定了,这个需求很现实,毕竟开发环境需要持续不断的编译、打包、部署等,而上线,则是一段时间才会运行一次的;因此,默认启用开发环境是最优的方案,Maven支持默认启用某个Profile,只需在<profile>内添加如下代码即可:

<activation>
<activeByDefault>true</activeByDefault>
</activation>

此处需要注意:一旦显式指定某个Profile,则该配置无效!

在实际开发中使用以上方式操作时,自然而然的会提出以下的问题:假如配置文件的信息很多,那么Profile的内容会很臃肿,不便于管理,如果能将配置信息从Profile抽取出来,独立放置,再根据不同的Profile去调用,如此就更好了!

Maven针对以上需求,确实有解决方案,就是使用<filters>标签,针对不同的环境,使用不同的文件替换原来配置文件中的变量。

项目根目录下新建如下目录和文件:

db.properties问标准的属性文件,kaifa/db.properties和shengchan/db.properties文件内容分别如下:

db.url=192.10.2.168
db.username=dbtest
db.password=dbtest
db.url=192.20.1.11
db.username=admin
db.password=comfreesecurity

将Profile中的属性信息抽取到了db.properties文件中,同时在Profile中添加<filters></filters>部分,修改后的代码如下:

<profiles>
<profile>
<id>kaifa</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<build>
<filters>
<filter>${basedir}/filters/kaifa/db.properties</filter>
</filters>
</build>
</profile> <profile>
<id>shengchan</id>
<build>
<filters>
<filter>${basedir}/filters/shengchan/db.properties</filter>
</filters>
</build>
</profile>
</profiles>

添加了<filters><filter>...</filter></filters>部分,使用指定的文件内容替换原文件中的变量;

如此之后,使用Maven命令进行构建即可。

细心的人会发现,以上Profile中的filters部分,除了使用的目录名称不同之外,其他代码全部相同,重复!!!

如果再多几个环境的话,代码冗余可想而知,因此需要优化,其实方法很简单,还是使用变量替换,修改后的pom.xml文件内容如下:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.test</groupId>
<artifactId>Profile</artifactId>
<version>0.0.1-SNAPSHOT</version> <build>
<resources>
<resource>
<directory>${project.basedir}/src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
<filters>
<filter>${basedir}/filters/${filters.env}/db.properties</filter>
</filters>
</build>
<profiles>
<profile>
<id>kaifa</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<filters.env>kaifa</filters.env>
</properties>
</profile> <profile>
<id>shengchan</id>
<properties>
<filters.env>shengchan</filters.env>
</properties>
</profile>
</profiles>
</project>

使用-P参数时,会激活<filters.env>属性,从而使用指定的过滤文件进行变量替换。

其实,以上方式使用久了,还是会有些想法,既然用变量,也就是说,必须使用Maven命令之后,才能部署到Tomcat等服务器中,多次重复的操作,还是有相当多的时间浪费在maven命令上,尤其在改动很少的代码的情况下;

此时又会提出新的需求,能否在不使用maven命令的情况下即可进行日常开发;测试环境(或生产环境)打包时,使用Maven命令和-P参数指定环境进行打包呢?

很幸运,Juven Xu--国内Maven第一人--为我们提供了这样的一个插件portable-config-maven-plugin,使用该插件,可以在不改变原有代码的基础上,进行不同环境的打包;其原理是使用内容替换(而不是变量替换);

插件代码地址:https://github.com/juven/portable-config-maven-plugin,目前最新版本为1.1.4;

该插件使用方法如下:

假设src/main/resources/db.properties文件代码如下:

database.jdbc.username=dev
database.jdbc.password=dev_pwd

对于测试环境,创建一个属性替换文件src/main/portable/test.xml,代码如下:

<?xml version="1.0" encoding="utf-8" ?>
<portable-config>
<config-file path="WEB-INF/classes/db.properties">
<replace key="database.jdbc.username">test</replace>
<replace key="database.jdbc.password">test_pwd</replace>
</config-file>
</portable-config>

此文件为替换内容描述文件,<config-file>标签的path属性的值是基于war包的相对路径,指需要被内容替换的文件;

配置portable-config-maven-plugin插件(该插件默认绑定到package声明周期):

<plugin>
<groupId>com.juvenxu.portable-config-maven-plugin</groupId>
<artifactId>portable-config-maven-plugin</artifactId>
<version>1.1.4</version>
<executions>
<execution>
<goals>
<goal>replace-package</goal>
</goals>
</execution>
</executions>
<configuration>
<portableConfig>src/main/portable/test.xml</portableConfig>
</configuration>
</plugin>

或在命令行指定替换内容描述文件:mvn clean package -DportableConfig="src/main/portable/test.xml"

打包完成后,db.properties文件内容会被替换。

该插件目前支持的内容替换文件格式有:

.properties

database.jdbc.username=dev
database.jdbc.password=dev_pwd

使用

<replace key="database.jdbc.username">test</replace>
<replace key="database.jdbc.password">test_pwd</replace>

替换为:

database.jdbc.username=test
database.jdbc.password=test_pwd

.xml

xml元素和属性可以使用xPath进行替换

<?xml version="1.0" encoding="UTF-8"?>
<server>
<port>8080</port>
<hosts>
<host id="1">localhost</host>
<host id="2">localhost</host>
</hosts>
<mode value="debug" />
</server>

使用

<replace xpath="/server/port">80</replace>
<replace xpath="//host/[@id='1']">192.168.1.1</replace>
<replace xpath="//host/[@id='2']">192.168.1.2</replace>
<replace xpath="/server/mode/@value">run</replace>

替换为:

<?xml version="1.0" encoding="UTF-8"?>
<server>
<port>80</port>
<hosts>
<host id="1">192.168.1.1</host>
<host id="2">192.168.1.2</host>
</hosts>
<mode value="run"/>
</server>

.sh

无引号、单引号、双引号、输出的shell变量可被替换

BIN_HOME=/tmp/bin
OUT_HOME="/tmp/out"
LOG_HOME='/tmp/log'
export APP_HOME="/tmp/app"

使用

<replace key="BIN_HOME">/home/juven/bin</replace>
<replace key="OUT_HOME">/home/juven/out</replace>
<replace key="LOG_HOME">/home/juven/log</replace>
<replace key="APP_HOME">/home/juven/app</replace>

替换为:

BIN_HOME=/home/juven/bin
OUT_HOME="/home/juven/out"
LOG_HOME='/home/juven/log'
export APP_HOME="/home/juven/app"

假如有个key=value类型的配置文件,但扩展名不是.properties,可按照以下方式指定:

<?xml version="1.0" encoding="utf-8" ?>
<portable-config>
<config-file path="db.ini" type=".properties">
<replace key="mysql.host">192.168.1.100</replace>
</config-file>
</portable-config>

使用type属性强制指定文件类型。
对该插件的介绍到此为止。

回头看看,发现内容和标题不符,说是介绍portable-config-maven-plugin插件,却花了大篇幅的内容介绍了Maven其他的标签使用,不过以上内容总有相同之处--针对不同环境打包的一些解决方法

Maven插件之portable-config-maven-plugin(不同环境打包)的更多相关文章

  1. Java学习01-使用maven插件tomcat搭建web maven项目

    我使用社区版的IDEA,社区版的没有tomcat插件,只能使用maven插件进行tomcat的使用了,下面进入正题 一.pom.xml配置tomcat插件 <build> <fina ...

  2. Spring Boot的Maven插件Spring Boot Maven plugin详解

    Spring Boot的Maven插件(Spring Boot Maven plugin)能够以Maven的方式为应用提供Spring Boot的支持,即为Spring Boot应用提供了执行Mave ...

  3. Maven插件系列之spring-boot-maven-plugin

    Spring Boot的Maven插件(Spring Boot Maven plugin)能够以Maven的方式为应用提供Spring Boot的支持,即为Spring Boot应用提供了执行Mave ...

  4. 自定义maven插件

    之前虽然一直知道maven插件是可以自定义的,不过一致没有用过.最近接触到了swagger项目中的codegen自动生成代码的功能,并且在codegen源码中,也是存在maven插件功能的,所以自己就 ...

  5. Java-Maven-Runoob:Maven 插件

    ylbtech-Java-Maven-Runoob:Maven 插件 1.返回顶部 1. Maven 插件 Maven 有以下三个标准的生命周期: clean:项目清理的处理 default(或 bu ...

  6. Maven插件构建Docker镜像

    背景 微服务架构下,微服务在带来良好的设计和架构理念的同时,也带来了运维上的额外复杂性,尤其是在服务部署和服务监控上.单体应用是集中式的,就一个单体跑在一起,部署和管理的时候非常简单,而微服务是一个网 ...

  7. 使用JaCoCo Maven插件创建代码覆盖率报告

    这篇博客文章描述了我们如何使用JaCoCo Maven插件为单元和集成测试创建代码覆盖率报告. 我们的构建要求如下: 运行测试时,我们的构建必须为单元测试和集成测试创建代码覆盖率报告. 代码覆盖率报告 ...

  8. Maven插件mybatis-generator,如何让生成的PO类的field上有对应表字段的注释

    前言 去年刚入职的时候,我就发现,po类(和数据库表对应的类)上,一片都是光秃秃的,什么注释都没有,类上没注释,field上也没注释. 在以前的项目中,其实我们都是有生成注释的,比如,对于下面这个表: ...

  9. maven插件:tomcat插件和jetty插件的区别

    在程序是多模块结构的时候,使用tomcat的maven插件和jetty的maven插件有细微差别: 1.tomcat7-maven-plugin   可以直接在parent的邮件直接运行:tomcat ...

  10. 在Eclipse中使用Maven插件 博客分类: Java相关技术

    简介 本文介绍如何在Eclipse中通过maven插件编写java项目和web项目. 安装Maven 下载Maven最新版本,见:maven.apache.org/download.html 当前版本 ...

随机推荐

  1. USACO Money Systems Dp 01背包

    一道经典的Dp..01背包 定义dp[i] 为需要构造的数字为i 的所有方法数 一开始的时候是这么想的 for(i = 1; i <= N; ++i){ for(j = 1; j <= V ...

  2. ZOJ2849 优先队列BFS

    Attack of Panda Virus Time Limit: 3 Seconds      Memory Limit: 32768 KB In recent months, a computer ...

  3. Chapter 4.开放-封闭原则

    开放-封闭原则:是说软件实体应该可以扩展,但不可修改. 设计人员必须对于他设计的模块应该对哪种变化封闭做出选择,先猜测出最有可能发生的变化种类,然后构造抽象来隔离那些变化. 面对需求,对程序的改动是通 ...

  4. Android HttpClient HttpURLConnection相关介绍

    Android HttpClient HttpURLConnection相关介绍 遇到一个问题 在android studio上用HttpClient编写网络访问代码的时候,发现该类无法导入并使用.. ...

  5. 基于Sql Server 2008的分布式数据库的实践(二)

    原文 基于Sql Server 2008的分布式数据库的实践(二) 从Win7连接Win2003的Sql Server 2008 1.新建链接服务器链接到Win2003的Sql Server 2008 ...

  6. 为什么C语言在2013年仍然很重要:一个简单的例子

    附注:在最初的文章里,我没说明进行模2^64的计算——我当然明白那些不是“正确的”斐波那契数列,其实我不是想分析大数,我只是想探寻编译器产生的代码和计算机体系结构而已. 最近,我一直在开发Dynvm— ...

  7. 【Dior风格/舒适防风面料/抗静电里衬/大身撞色拼接/精致平驳领/时尚便西款/蓝绿色】玛萨玛索男装网购商城

    [Dior风格/舒适防风面料/抗静电里衬/大身撞色拼接/精致平驳领/时尚便西款/蓝绿色]玛萨玛索男装网购商城 [特价商品] Dior风格/舒适防风面料/抗静电里衬/大身撞色拼接/精致平驳领/时尚便西款 ...

  8. 一步一步重写 CodeIgniter 框架 (6) —— 实现在控制器Controller中加载View

    1. 控制器将模型类获得的数据,传递给视图进行显示,所以视图必须负责接收数据,另外重要的一点是当模型和视图分开后,多个模型的数据可以传递给一个视图进行展示,也可以说一个模型的数据在多个不同的视图中进行 ...

  9. Java开发中常见的危险信号(上)

    本文来源于我在InfoQ中文站原创的文章,原文地址是:http://www.infoq.com/cn/news/2013/12/common-red-flags-in-java-1 Dustin Ma ...

  10. 修改linux文件权限命令:chmod 【转载】

    Linux系统中的每个文件和目录都有访问许可权限,用它来确定谁可以通过何种方式对文件和目录进行访问和操作. chmod  命令可以改变所有子目录的权限,下面有2种方法 改变一个文件的权限: chmod ...