为了解决程序可移植性的问题,Maven 2.0 开始引入了 profile 的概念。
那什么是程序的可移植性问题呢?简单来说就是在一个地方构建和运行是成功的,但是在另一个地方构建或运行却失败了,这样的程序就出了可移植性问题。在基于 Maven 的 java 工程中,我们经常遇到的可移植性问题主要有如下几种:
- 插件可能会被配置一些本地路径
- 比如 maven-protoc-plugin 这个插件需要配置一个 protocExecutable 属性来指定编译 proto 文件所用的 protoc 编译器路径,这是一个本地路径,而且不同机器上的路径有可能是不一致的。
- 一些依赖版本的变更也是不可避免的;
- 我在具体实践的时候就遇到这种坑爹的情况,公司有两个 hadoop 集群,且两个集群的 hadoop 版本不一致,因此我的 map-reduce 任务运行在不同集群的时候就需要配置不同的 hadoop 版本依赖。
- 工程的 artifact 名字也可能会被调整;
- 这种情况偶还没有遇到过。
- 你甚至可能需要在检测到某些特殊构建环境后需要包含整个构建插件。
- 比如说你的工程发现需要编译 proto 文件的时候,你就需要把 maven-protoc-plugin 这个插件引入进来,而其他时候这个是不需要的。
Maven 的 profile 机制是怎么解决上面的问题的呢?总的思路很简单,就是在构建 Maven 工程的时候动态插入、篡改 pom 配置。举个例子:
假设你的工程中使用到了 hadoop,其版本是 2.6.0,那么你在工程中的配置应该类似下面这样:
<properties> <hadoop.version>2.6.0</hadoop.version> </properties> <dependencyManagement> <dependencies> <dependency> <groupId>org.apache.hadoop</groupId> <artifactId>hadoop-auth</artifactId> <version>${hadoop.version}</version> </dependency> </dependencies> </dependencyManagement>
但突然悲催地发现另外一个 hadoop 目标集群的版本是 2.0.0-cdh4.1.2,怎么办?这时候 profile 就派上用场了,我们可以像下面这样在 pom.xml 中配置一个 profile:
<profiles> <!-- 针对 apps 低版本 hadoop 集群的特别 profile 配置 --> <profile> <id>on-lower-hadoop</id> <properties> <hadoop.version>2.0.0-cdh4.1.2</hadoop.version> </properties> </profile> </profiles>
在工程编译的时候触发这个 profile:
mvn clean install -P on-lower-hadoop
这样在构建的时候依赖的 hadoop 版本就被改成了 2.0.0-cdh4.1.2。