maven调用ant:初学maven(4)-使用maven ant task实现非标准打包

  maven很强大但是总有些事情干起来不是得心应手没有使用ant时那种想如何干就如何干流畅感尤其当要打包个特殊(相对maven标准架构而且)时常有不知所措感觉当然这个应该和自己对maven了解不够有关毕竟“初学maven”嘛

  但是maven在依赖管理方面实在是太强大了太喜欢退回原来ant方式完全不可能我想用过maven般是不会有回到原来在cvs,subversion中checkin/checkout n个jar包时代仅此项理由就足够继续坚持使用maven了

  然而ant灵活又难于忘怀尤其是从antbuild.xml路走来总是回不知不觉间想到ant美好鱼和熊掌我都想要最近想打包个java应用很简单但即不是标准j2ee appication也不是web application, 用maven完全不知道该如何打包package出来完全不是我想要在网上 4处google maven资料时候总有用回ant拉倒冲动

  先交代下背景吧我要打包是这个样子:

  demo1
  |____lib
  |_____demo1.jar
  |_____*****.jar
  |_____*****.jar
  |____config
  |_____*****.properties
  |_____*****.xml
  |____log
  |_____*****.log
  |____run.bat
  |____run.sh


  这个应用打包模式很简单个bat或者sh脚本用来执行lib目录下存放所有jar包包括自己源代码编译打包jar和第 3方包config下是配置文件这些文件需要在安装时或者运行前修改比如监听端口啊数据库信息的类log目录存放日志文件最后打包产物是个zip包(或者tar,tar.gz)

  遇到问题就是maven标准打包方式中根本不考虑类似情况什么jarearwar完全不适用而且maven有些理念也诧异比如maven标准config目录是src//config但是这个目录里面配置文件默认会打包到jar包中都在jar里面了还让人如何改啊?

  本着尽量只用maven不用ant想法我在maven资料中看了好久没有找到解决思路方法难道大家都只打包标准earjarwar只有我这样无聊人才会有这种打包需求?

  几经寻觅和探索最后发现maven ant tasks似乎是个不错选择带着mavenanttasks官方文档和google上搜到几篇文章开始尝试成功实现功能现在将过程和思路方法share给大家

  首先建立java项目anttaskdemo1按照maven推荐文件结构如下:

  anttaskdemo1
  |____src//java
  |____src//config
  |____src//bin
  |____src//resources
  |____src/test/java
  |____src/test/resources
  |____target
  |____build.properties
  |____build.xml
  |____pom.xml


  其中src//java下放java代码;src//resources下放个*.properties文件这个资源文件是打包到jar中内容打包的后不需要改变src//config下放个标准log4j.xml这个是有在安装运行前临时修改需要src//bin下放置可执行文件

  1. 首先看pom.xml标准内容很简单象征性加入几个依赖

<dependency>
      <groupId>commons-codec</groupId>
      <artactId>commons-codec</artactId>
      <version>1.3</version>
    </dependency>
    <dependency>
      <groupId>log4j</groupId>
      <artactId>log4j</artactId>
      <version>1.2.13</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>org.testng</groupId>
      <artactId>testng</artactId>
      <version>5.8</version>
      <scope>test</scope>
      <ier>jdk15</ier>
    </dependency>


  其中commons-codeclog4j是需要打包到lib中运行时需要testng(或者更junit)是用来单元测试不需要打包到lib中请注意它设置"<scope>test</scope>"

  2. 然后看看build.properties文件这个内容不多:

  M2_REPO=G:/soft/maven/localRepository

path.package=package
path.target.name=anttaskdemo1
path.package.lib=lib
path.package.log=log
path.package.config=config
path.package.bin=


  M2_REPO稍后再详谈后面path.package的类是最终打包时使用几个目录名称对应于最终打包结构

  3. build.xml这个内容比较多  
<?xmlversion="1.0"encoding="UTF-8"?>
<projectname="demo"default="all"xmlns:artact="urn:maven-artact-ant">
  <description>
  </description>
  <propertyfile="build.properties"/>
  <targetname="init_maven">
    <!--
    remembertoM2_REPObeforeuhisbuild.xml,forexampleineclispe:
    "Window→Preferences→Ant→Runtime",addapropertynamed"M2_REPO"anditvaluepotothepathofyourmaven
    localrepository;Oryoucanitinbuild.properties. Youneeddoone(andonlyone)ofthem.
    -->
    <pathid="maven-ant-tasks.path"path="${M2_REPO}/org/apache/maven/maven-ant-tasks/2.0.9/maven-ant-tasks-2.0.9.jar"/>
    <typedefresource="org/apache/maven/artact/ant/antlib.xml"uri="urn:maven-artact-ant"pathref="maven-ant-tasks.path"/>
    <artact:pomid="maven.project"file="pom.xml"/>
    <artact:dependenciespathId="path.build"fileid="maven.file.build">
      <pomrefid="maven.project"/>
    </artact:dependencies>
    <artact:dependenciespathId="path.runtime"fileid="maven.file.runtime"useScope="runtime">
      <pomrefid="maven.project"/>
    </artact:dependencies>
  </target>
  <targetname="all"depends="init_path,compile,jar,package,zip"description="doall">
    <echo>begodoalltargettobuildtheresultpackage.</echo>
  </target>
  <targetname="maven_info"depends="init_maven">
    <echo>Mavenbuilddirectoryis${maven.project.build.directory}</echo>
    <echo>MavenbuildfinalNameis${maven.project.build.finalName}</echo>
    <echo>MavenbuildsourceDirectorydirectoryis${maven.project.build.sourceDirectory}</echo>
    <echo>MavenbuildoutputDirectorydirectoryis${maven.project.build.outputDirectory}</echo>
    <echo>MavenbuildscriptSourceDirectorydirectoryis${maven.project.build.testSourceDirectory}</echo>
    <echo>MavenbuildtestOutputDirectorydirectoryis${maven.project.build.testOutputDirectory}</echo>
    <echo>MavenbuildscriptSourceDirectorydirectoryis${maven.project.build.scriptSourceDirectory}</echo>
    <echo>MavenbuildresourceDirectorydirectoryis${maven.project.build.resources}</echo>
    <propertyname="target.jar.name"value="${maven.project.build.directory}/${maven.project.build.finalName}.jar"/>
    <echo>MavenbuildscriptSourceDirectorydirectoryis${target.jar.name}</echo>
  </target>
  <targetname="clean"depends="init_maven">
    <echo>cleanbuilddirectory:${maven.project.build.directory}</echo>
    <deletedir="${maven.project.build.directory}"s="**/*"/>
  </target>
  <targetname="init_path"depends="maven_info,clean">
    <echo>makedirforjavacompile:${maven.project.build.outputDirectory}</echo>
    <mkdirdir="${maven.project.build.outputDirectory}"/>
  </target>
  <targetname="compile"description="description"depends="init_maven">
    <javacsrcdir="${maven.project.build.sourceDirectory}"destdir="${maven.project.build.outputDirectory}"pathref="path.build"/>
  </target>
  <targetname="copyResource"depends="init_maven">
    <copytodir="${maven.project.build.outputDirectory}">
      <filedir="src//resources">
      </file>
    </copy>
  </target>
  <targetname="jar"depends="compile,copyResource">
    <deletefile="${maven.project.build.directory}/${maven.project.build.finalName}.jar" failonerror="false"/>
    <jardestfile="${maven.project.build.directory}/${maven.project.build.finalName}.jar"basedir="${maven.project.build.outputDirectory}">
    </jar>
  </target>
  <targetname="package"depends="package_prepare,copyLib,copyConfig,copyBin">
  </target>
  <targetname="package_prepare"depends="init_maven">
    <echo>cleanpackagedirectory:${maven.project.build.directory}/${path.package}</echo>
    <deletedir="${maven.project.build.directory}/${path.package}"/>
    <mkdirdir="${maven.project.build.directory}/${path.package}"/>
    <mkdirdir="${maven.project.build.directory}/${path.package}/${path.target.name}"/>
    <mkdirdir="${maven.project.build.directory}/${path.package}/${path.target.name}/${path.package.lib}"/>
    <mkdirdir="${maven.project.build.directory}/${path.package}/${path.target.name}/${path.package.config}"/>
    <mkdirdir="${maven.project.build.directory}/${path.package}/${path.target.name}/${path.package.log}"/>
  </target>
  <targetname="copyLib"depends="init_maven">
    <copytodir="${maven.project.build.directory}/${path.package}/${path.target.name}/${path.package.lib}">
      <filerefid="maven.file.runtime"/>
      <mappertype="flatten"/>
    </copy>
    <copytodir="${maven.project.build.directory}/${path.package}/${path.target.name}/${path.package.lib}"
      file="${maven.project.build.directory}/${maven.project.build.finalName}.jar">
    </copy>
  </target>
  <targetname="copyConfig"depends="init_maven">
    <copytodir="${maven.project.build.directory}/${path.package}/${path.target.name}/${path.package.config}">
      <filedir="src//config">
      </file>
    </copy>
  </target>
  <targetname="copyBin"depends="init_maven">
    <copytodir="${maven.project.build.directory}/${path.package}/${path.target.name}/${path.package.bin}">
      <filedir="src//bin">
      </file>
    </copy>
  </target>
  <targetname="zip"depends="init_maven">
    <zipdestfile="${maven.project.build.directory}/${path.package}/${path.target.name}.zip">
      <filedir="${maven.project.build.directory}/${path.package}/${path.target.name}"></file>
    </zip>
  </target>
</project>


  步来讲吧:

  3.1 最重要init_maven

  <targetname="init_maven">
    <!--
    remembertoM2_REPObeforeuhisbuild.xml,forexampleineclispe:
    "Window→Preferences→Ant→Runtime",addapropertynamed"M2_REPO"anditvaluepotothepathofyourmaven
    localrepository;Oryoucanitinbuild.properties. Youneeddoone(andonlyone)ofthem.
    -->
    <pathid="maven-ant-tasks.path"path="${M2_REPO}/org/apache/maven/maven-ant-tasks/2.0.9/maven-ant-tasks-2.0.9.jar"/>
    <typedefresource="org/apache/maven/artact/ant/antlib.xml"uri="urn:maven-artact-ant"pathref="maven-ant-tasks.path"/>
    <artact:pomid="maven.project"file="pom.xml"/>
    <artact:dependenciespathId="path.build"fileid="maven.file.build">
      <pomrefid="maven.project"/>
    </artact:dependencies>
    <artact:dependenciespathId="path.runtime"fileid="maven.file.runtime"useScope="runtime">
      <pomrefid="maven.project"/>
    </artact:dependencies>
  </target>


  在ant中使用maven-ant-tasks就需要装载maven-ant-tasksjar包思路方法有两种种是直接将maven-ant-tasks-2.0.9.jar放到antlib下自然就可以直接使用但是个人感觉不如何喜欢这种方式我采用是第 2种在antbuild.xml文件中装载:

    <pathid="maven-ant-tasks.path"path="${M2_REPO}/org/apache/maven/maven-ant-tasks/2.0.9/maven-ant-tasks-2.0.9.jar"/>
    <typedefresource="org/apache/maven/artact/ant/antlib.xml"uri="urn:maven-artact-ant"pathref="maven-ant-tasks.path"/>


  这样就可以在后面使用maven-ant-taskstask比如artact:pomartact:dependencies<path />用于指定maven-ant-tasks-2.0.9.jar路径这里就有点麻烦了:maven-ant-tasks-2.0.9.jar这个东西放哪里好呢?直接放到项目中然后存放到cvs/svn?显然不是个好办法考虑到maven本来就是干保存jar这行交给maven好了maven-ant-tasks-2.0.9.jar本来就是个依赖可以在http://mvnrepository.com/找到:

  http://mvnrepository.com/artact/org.apache.maven/maven-ant-tasks

  pom内容如下:

  <dependency>
  <groupId>org.apache.maven</groupId>
  <artactId>maven-ant-tasks</artactId>
  <version>2.0.9</version>
</dependency>


  将这个内容随便找个空项目加入后update下dependency在本地maven repository中就会有它jar文件然后就可以直接使用它

  ${M2_REPO}这个是eclipse中通用指向maven local repository变量大家使用maven命令建立eclipse项目时会遇到它我们在这里可以直接使用这个变量来访问maven local repository如果没有建立这个变量请自行建立上面注释中有详细介绍说明如果在eclispe的外比如命令行直接运行ant打包则可以通过设置build.properties文件中“M2_REPO=G:/soft/maven/localRepository”来指定(这里用到ant个特性属性旦被赋值就不能修改因此第次赋值有效在eclispe中运行M2_REPO会使用eclispe中设置如果eclispe没有设置或者命令行直接运行M2_REPO属性会在build.properties文件装载时设置)

  装载ok后接着是artact:pom和artact:dependencies 任务来指定pom.xml文件再得到dependencies信息后面编译打包会使用到注意useScope="runtime"这个是为了最后打包时使用只复制runtie时需要jar包

  <target name="maven_info" />是用来打印maven相关些信息比如maven下几个build目录artact:pom任务装载了整个pom因此在后面可以访问到pom信息比如${maven.project.build.sourceDirectory}是java源代码目录${maven.project.build.finalName}是最终名称

  pom内容可以参考这两个官方资料:

  1) maven model

  http://maven.apache.org/ref/2.0.9/maven-model/maven.html

  2) Introduction to the POM

  http://maven.apache.org/guides/roduction/roduction-to-the-pom.html

  标准目录布局可以参考这个官方资料:

  http://maven.apache.org/guides/roduction/roduction-to-the-standard-directory-layout.html

  3.2 compile

  这里是maven ant task精髓所在

  <targetname="compile"description="description"depends="init_maven">
    <javacsrcdir="${maven.project.build.sourceDirectory}"destdir="${maven.project.build.outputDirectory}"pathref="path.build"/>
  </target>


  结合的前maven化时情况:

    <artact:pomid="maven.project"file="pom.xml"/>
    <artact:dependenciespathId="path.build"fileid="maven.file.build">
      <pomrefid="maven.project"/>
    </artact:dependencies>


  可以看到我们项目完全遵循maven标准做法然后ant通过访问pom来得到相关路径信息和path信息完美结合

  target copyResource 完成了将resource copy到outputDirectory任务这里resource都是path resource

  注: 这个有个问题就是我没有找到通过pom得到resouce目录思路方法${maven.project.build.resources 只能得到pom文件中<resources/>, 对于里面包含<resource>不知道该用什么方式来访问如默认:

  <resources>
   <resource>
    <directory>src//resources</directory>
   </resource>
  </resources>


  我试过用${maven.project.build.resources[0];${maven.project.build.resources(0), ${maven.project.build.resources.0,${maven.project.build.resources.resource

  等都无效找了很久都没有找到资料只好作罢直接写死src//resources吧

  3.3 jar

  和compile类似标准ant jar然后通过访问pom来得到相关路径信息和打包文件名注意这里文件名和路径和maven做法也就是说和执行mavencompile命令结果是

  <targetname="jar"depends="compile,copyResource">
    <deletefile="${maven.project.build.directory}/${maven.project.build.finalName}.jar" failonerror="false"/>
    <jardestfile="${maven.project.build.directory}/${maven.project.build.finalName}.jar"basedir="${maven.project.build.outputDirectory}">
    </jar>
  </target>


  3.4 package zip

  package_prepare, copyLib, copyConfig, copyBin 这几个target都简单体力活而已zip也是

  4. 整理总结

  上面内容虽多但是整理总结起来就只有两点:

  1. maven ant task可以将maven功能和ant灵活性统起来对于非标准打包情况非常适用

  2. maven ant task使用并不难不过需要掌握不少maven基本知识比如pom标准目录布局等

  另外似乎ant + Ivy会是更好选择?

  相关文章:

  初学maven(1)-常见小问题集锦

  初学maven(2)-maven/artactory/m2eclipse安装全过程

  初学maven(3)-使用nexus替代artactory作为maven私服



  初学maven(4)-使用maven ant task实现非标准打包

  初学maven(5)-使用assembly plugin实现自定义打包



Tags:  maven anttask ant打包 maven调用ant

延伸阅读

最新评论

发表评论