大型项目中,分开发环境、测试环境、生产环境等;
不同环境,配置不同,或数据源,或服务器,或数据库等;
问题来了,如何使用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
Maven提供的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}
<resources> <resource> <directory>${project.basedir}/src/main/resources</directory> <filtering>true</filtering> </resource> </resources>
mvn package -Pkaifa
mvn package -Pshengchan
如此即可。
此命令用的多了,就会发现,两个环境必选其一,如果能设置其一个为默认开启,就不用每次都手动指定了,这个需求很现实,毕竟开发环境需要持续不断的编译、打包、部署等,而上线,则是一段时间才会运行一次的;因此,默认启用开发环境是最优的方案,Maven支持默认启用某个Profile,只需在<profile>内添加如下代码即可:
<activation> <activeByDefault>true</activeByDefault> </activation>
在实际开发中使用以上方式操作时,自然而然的会提出以下的问题:假如配置文件的信息很多,那么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=confreesecurity
<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部分,除了使用的目录名称不同之外,其他代码全部相同,重复!!!<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>
很幸运,Juven Xu--国内Maven第一人--为我们提供了这样的一个插件portable-config-maven-plugin,使用该插件,可以在不改变原有代码的基础上,进行不同环境的打包。
------以下应该算作最佳实践了
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
<?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>
<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>
该插件目前支持的内容替换文件格式有:
.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"
类似.properties格式
假如有个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其他的标签使用,不过以上内容总有相同之处--针对不同环境打包的一些解决方法。