Maven使构建变得规范、简便,但在某些时候还是感觉Ant更容易控制,把两者结合起来使构建变得更加灵活。Maven所定义的构建模型,再加上一些Plugin的帮助,让我们每容易的实现两者的结合。下面看个例子。
一个例子
项目中遇到这样一个问题,程序要检查某种License,License的版本号在另外的配置文件中定义。基于安全考虑,最好把版本号在编译期就写到某个常量中,而不在运行期读取某配置文件。假设我们要把版本号写入到某个enum类型的常量里,之前我们可以准备它模块文件。所以基本的构建流程如下:
- 准备源文件
- 读取License版本号
- 读取Java模版文件
- 版本号替换
- 生成Java源文件包含最新的版本号
- 编译源文件
- 测试
- 打包
- …
实现
先看如下的代码目录结构(所用代码都在Github上)。
- ant_replace_license_version.xml是Maven将要调用的Ant脚本
- ant-contrib-1.0b3.jar包含了很多ant的扩展,有很多非常Powerful的工具。在这个例子中我会使用loadfile, propertyregex等功能。
- License.template是License.java的模板文件
- pom.xml是maven脚本
- version.h是一个C/C++的头文件,里面定义了VERSION
构建过程就是要把version.h里版本号取出,替换模板文件里的占位符,然后生成真正的License类,并放到包com.innoli.sample中,由App调用。
具体文件内容
version.h
1 |
#define VERSION 1.0.2qa2 |
License.template
1 2 3 4 5 6 7 8 9 10 11 12 13 |
package com.innoli.sample; /** * Created by yli on 5/31/15. */ public interface License { /** * License version. */ String VERSION = "[license_version]"; } |
ant_replace_license_version.xml
使用了ant-contrib的扩展,完成了读取、查找、替换、生成新的类文件等工作。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <project basedir="." default="get_version" name="change gui version"> <taskdef resource="net/sf/antcontrib/antlib.xml"> <classpath> <pathelement location="./ant-contrib-1.0b3.jar"/> </classpath> </taskdef> <property name="version_include_file" location=".\\version.h"/> <property name="file_template" location="License.template"/> <property name="class_file" location="src\\main\\java\\com\\innoli\\sample\\License.java"/> <target name="clean"> <echo message="Remove ${class_file}..."/> <delete file="${class_file}"/> <echo message="Clean done."/> </target> <target name="get_version" depends="clean"> <echo message="Retrieve the version from ${version_include_file}..."/> <loadfile srcFile="${version_include_file}" property="version_line"> <filterchain> <linecontains> <contains value="VERSION"/> </linecontains> </filterchain> </loadfile> <propertyregex property="version" input="${version_line}" regexp=".*VERSION\s*(\d+[.]\d+[.]\d+).*$" select="\1"/> <loadfile srcFile="${file_template}" property="template_content"/> <propertyregex property="final_content" input="${template_content}" regexp="\[license_version\]" replace="${version}" global="true"/> <echo message="Get version ${version}"/> <echo message="Generate new ${class_file}..."/> <echo file="${class_file}" append="false">${final_content}</echo> <echo message="New ${class_file} is ready."/> </target> </project> |
pom.xml
使用了exec-maven-plugin来调用ant脚本,也可以使用Apache Maven AntRun Plugin, 但它MS使用了很旧的ant。在process-resources阶段,生成License类。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 |
<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>org.innoli.sample</groupId> <artifactId>mavenant</artifactId> <version>1.0-SNAPSHOT</version> <packaging>jar</packaging> <name>mavenant</name> <url>http://maven.apache.org</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <build> <plugins> <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>exec-maven-plugin</artifactId> <version>1.2.1</version> <executions> <execution> <id>ant-get-version</id> <phase>process-resources</phase> <goals> <goal>exec</goal> </goals> <configuration> <executable>ant</executable> <workingDirectory>${basedir}</workingDirectory> <arguments> <argument>-f</argument> <argument>${basedir}/ant_replace_license_version.xml</argument> <argument>get_version</argument> </arguments> </configuration> </execution> <execution> <id>ant-version-clean</id> <phase>clean</phase> <goals> <goal>exec</goal> </goals> <configuration> <executable>ant</executable> <workingDirectory>${basedir}</workingDirectory> <arguments> <argument>-f</argument> <argument>${basedir}/ant_replace_license_version.xml</argument> <argument>clean</argument> </arguments> </configuration> </execution> </executions> </plugin> </plugins> </build> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> </dependencies> </project> |
编译
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
/home/yli/bin/jdk1.8.0_45/bin/java -Dmaven.home=/home/yli/bin/idea-IC-141.1010.3/plugins/maven/lib/maven3 -Dclassworlds.conf=/home/yli/bin/idea-IC-141.1010.3/plugins/maven/lib/maven3/bin/m2.conf -Didea.launcher.port=7534 -Didea.launcher.bin.path=/home/yli/bin/idea-IC-141.1010.3/bin -Dfile.encoding=UTF-8 -classpath /home/yli/bin/idea-IC-141.1010.3/plugins/maven/lib/maven3/boot/plexus-classworlds-2.4.jar:/home/yli/bin/idea-IC-141.1010.3/lib/idea_rt.jar com.intellij.rt.execution.application.AppMain org.codehaus.classworlds.Launcher -Didea.version=14.1.3 compile [INFO] Scanning for projects... [INFO] [INFO] ------------------------------------------------------------------------ [INFO] Building mavenant 1.0-SNAPSHOT [INFO] ------------------------------------------------------------------------ [INFO] [INFO] --- maven-resources-plugin:2.5:resources (default-resources) @ mavenant --- [debug] execute contextualize [INFO] Using 'UTF-8' encoding to copy filtered resources. [INFO] skip non existing resourceDirectory /home/yli/source/MavenAnt/src/main/resources [INFO] [INFO] --- exec-maven-plugin:1.2.1:exec (ant-get-version) @ mavenant --- Buildfile: /home/yli/source/MavenAnt/ant_replace_license_version.xml clean: [echo] Remove /home/yli/source/MavenAnt/src/main/java/com/innoli/sample/License.java... [echo] Clean done. get_version: [echo] Retrieve the version from /home/yli/source/MavenAnt/version.h... [echo] Get version 1.0.2 [echo] Generate new /home/yli/source/MavenAnt/src/main/java/com/innoli/sample/License.java... [echo] New /home/yli/source/MavenAnt/src/main/java/com/innoli/sample/License.java is ready. BUILD SUCCESSFUL Total time: 0 seconds [INFO] [INFO] --- maven-compiler-plugin:2.3.2:compile (default-compile) @ mavenant --- [INFO] Compiling 2 source files to /home/yli/source/MavenAnt/target/classes [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 1.111s [INFO] Finished at: Sun May 31 18:37:39 PDT 2015 [INFO] Final Memory: 21M/964M [INFO] ------------------------------------------------------------------------ Process finished with exit code 0 |
一切就是这么简单!