在大型的项目组中,分不同的开发环境,测试环境,生产环境(说白了就是配置文件不同,或者数据源,或者服务器,或者数据库等);问题来了,如何使用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. ognl中的#、%和$

    多学点,谢谢兄弟 原文地址:ognl中的#.%和$作者:百合 ognl中的#.%和$ #.%和$符号在OGNL表达式中经常出现,而这三种符号也是开发者不容易掌握和理解的部分.在这里笔者简单介绍它们的相 ...

  2. Best Component for Bitmap Image

    The best is to purchase ImageEn and use the latest version. Coz nothing compares to ImageEn.... But ...

  3. 从java main方法说开去(转)

    刚刚接触java语言时,接触的便为一个java main方法.我们知道这样程序就可以运行了,但是程序是怎么运行起来的我们却不知道. 众所周知,当执行一个java程序时,首先会启动一个JVM虚拟机进程, ...

  4. android大牛高焕堂最新力作-android架构师之路

    android大牛高焕堂 个人介绍: Android专家顾问,台湾Android论坛主席,现任亚太地区Android技术大会主席,台湾Android领域框架开发联盟总架构师.发表100多篇Androi ...

  5. HDOJ 1384 差分约束

    结题报告合集请戳:http://972169909-qq-com.iteye.com/blog/1185527 /*题意:求符合题意的最小集合的元素个数 题目要求的是求的最短路, 则对于 不等式 f( ...

  6. NYOJ10,skiing

    skiing 时间限制:3000 ms  |  内存限制:65535 KB 难度:5 描写叙述 Michael喜欢滑雪百这并不奇怪, 由于滑雪的确非常刺激.但是为了获得速度,滑的区域必须向下倾斜,并且 ...

  7. cocos2d-x2.0 win7第一次创建项目需要调用到的脚本(不断更新维护)//cocos2d-x 教程一

    第一步: 最新的cocos2d-x.下载地址https://github.com/cocos2d/cocos2d-x github上最新的引擎,值得注意的是官网上发布的引擎是稳定版.选择哪种就看个人喜 ...

  8. 创建Activity

     创建Activity 创建 Activity 分为3个步骤: 1.创建一个扩展子Activity的class 2.创建一个Layout 3.在 AndroidMainfest 中 配置这个Activ ...

  9. android保存文件到SD卡中

    想把文件保存到SD卡中,一定要知道SD卡的路径,有人说可以用File explore来查看,这种方法不太好,因为随着android版本的升级,SD卡的路径可能会发生改变.在1.6的时候SD的路径是/s ...

  10. 基于visual Studio2013解决C语言竞赛题之1015日期计算

        题目 解决代码及点评 /* 15. 已知某年不是闰年,给定该年某一天的月份和日期, 求这一天是该年的第几天. */ #include <stdio.h> #incl ...