- 浏览: 581678 次
- 性别:
- 来自: 广州
文章分类
- 全部博客 (188)
- java (14)
- web (14)
- web service (3)
- 杂谈 (14)
- Version Control (13)
- software test (30)
- linux (17)
- database (3)
- distributed storage and computing (1)
- ejb (7)
- project building (46)
- spring & IOC (2)
- Thread (2)
- xml (2)
- tool software (0)
- [网站分类]1.网站首页原创Java技术区(对首页文章的要求: 原创、高质量、经过认真思考并精心写作。BlogJava管理团队会对首页的文章进行管理。) (0)
- project manager (9)
- OSGI (1)
- nosql (3)
最新评论
-
sp42:
好搞笑
你懂不懂xml! (2) -
cherishmmo2004:
感觉你们都很牛掰,我们做的一个运维平台也是用karaf的,用k ...
基于osgi开发大型的企业应用 -
liubey:
“自作聪明”的使用了读写锁,其实只使用ReentrantLoc ...
编码最佳实践(4)--小心LinkedHashMap的get()方法 -
liubey:
你这个代码是sublist后仍然一直持有这个sub的引用,一般 ...
编码最佳实践(5)--小心!这只是冰山一角 -
xiegqooo:
初学maven(5)-使用assembly plugin实现自定义打包
maven很强大,但是总有些事情干起来不是得心应手,没有使用ant时那种想怎么干就怎么干的流畅感。尤其当要打包一个特殊(相对maven的标准架构而且)时,常有不知所措的感觉。当然这个应该和自己对maven的了解不够有关,毕竟,“初学maven”嘛。
但是maven在依赖管理方面实在是太强大了,太喜欢,退回原来的ant方式完全不可能,我想用过maven的人,一般是不会有回到原来在cvs,subversion中checkin/checkout n个jar包的时代,仅此一项理由就足够继续坚持使用maven了。
然而ant的灵活又难于忘怀,尤其是从ant的build.xml一路走来的人,总是回不知不觉间想到ant的美好。鱼与熊掌,我都想要。最近想打包一个java应用,很简单但即不是标准的j2ee appication也不是web application, 用maven完全不知道该怎么打包,package出来的完全不是我想要的,在网上四处google maven资料的时候,总有用回ant拉倒的冲动。
先交代一下背景吧,我要打包的程序,是这个样子:
demo1
|____lib
|_____demo1.jar
|_____*****.jar
|_____*****.jar
|____config
|_____*****.properties
|_____*****.xml
|____log
|_____*****.log
|____run.bat
|____run.sh
这个应用的打包模式很简单,一个bat或者sh脚本用来执行,lib目录下存放所有的jar包,包括自己的源代码编译打包的jar和第三方包。config下是配置文件,这些文件需要在安装时或者运行前修改,比如监听的端口啊,数据库信息之类的。log目录存放日志文件。最后打包的产物是一个zip包(或者tar,tar.gz)。
遇到的问题,就是maven标准的打包方式中根本不考虑类似的情况,什么jar,ear,war完全不适用。而且maven有些理念也诧异,比如maven标准的config目录是src/main/config,但是这个目录里面的配置文件默认会打包到jar包中,晕,都在jar里面了还让人怎么改啊?
本着尽量只用maven不用ant的想法,我在maven的资料中看了好久,没有找到解决的方法。晕,难道大家都只打包标准的ear,jar,war,只有我这样无聊的人才会有这种打包的需求?
几经寻觅和探索,最后发现,maven ant tasks似乎是一个不错的选择。带着mavenanttasks的官方文档和google上搜到的几篇文章,开始尝试,成功实现功能。现在将过程和方法share给大家。
首先建立java项目anttaskdemo1,按照maven的推荐,文件结构如下:
anttaskdemo1
|____src/main/java
|____src/main/config
|____src/main/bin
|____src/main/resources
|____src/test/java
|____src/test/resources
|____target
|____build.properties
|____build.xml
|____pom.xml
其中src/main/java下放java代码;src/main/resources下放一个*.properties文件,这个资源文件是打包到jar中,内容打包之后不需要改变的。src/main/config下放一个标准的log4j.xml,这个是有在安装运行前临时修改的需要的。src/main/bin下放置可执行文件。
1. 首先看pom.xml,标准内容,很简单,象征性的加入几个依赖
< groupId > commons-codec </ groupId >
< artifactId > commons-codec </ artifactId >
< version > 1.3 </ version >
</ dependency >
< dependency >
< groupId > log4j </ groupId >
< artifactId > log4j </ artifactId >
< version > 1.2.13 </ version >
< scope > compile </ scope >
</ dependency >
< dependency >
< groupId > org.testng </ groupId >
< artifactId > testng </ artifactId >
< version > 5.8 </ version >
< scope > test </ scope >
< classifier > jdk15 </ classifier >
</ dependency >
其中commons-codec,log4j是需要打包到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,这个内容比较多。
< project name ="demo" default ="all" xmlns:artifact ="urn:maven-artifact-ant" >
< description >
</ description >
< property file ="build.properties" />
< target name ="init_maven" >
<!--
remember to set M2_REPO before use this build.xml, for example in eclispe:
"Window→Preferences→Ant→Runtime", add a new property named "M2_REPO" and set it value point to the path of your maven
local repository; Or you can set it in build.properties. You need do one (and only one) of them.
-->
< path id ="maven-ant-tasks.classpath" path ="${M2_REPO}/org/apache/maven/maven-ant-tasks/2.0.9/maven-ant-tasks-2.0.9.jar" />
< typedef resource ="org/apache/maven/artifact/ant/antlib.xml" uri ="urn:maven-artifact-ant" classpathref ="maven-ant-tasks.classpath" />
< artifact:pom id ="maven.project" file ="pom.xml" />
< artifact:dependencies pathId ="classpath.build" filesetid ="maven.fileset.build" >
< pom refid ="maven.project" />
</ artifact:dependencies >
< artifact:dependencies pathId ="classpath.runtime" filesetid ="maven.fileset.runtime" useScope ="runtime" >
< pom refid ="maven.project" />
</ artifact:dependencies >
</ target >
< target name ="all" depends ="init_path, compile, jar, package, zip" description ="do all" >
< echo > begin to do all target to build the result package. </ echo >
</ target >
< target name ="maven_info" depends ="init_maven" >
< echo > Maven build directory is ${maven.project.build.directory} </ echo >
< echo > Maven build finalName is ${maven.project.build.finalName} </ echo >
< echo > Maven build sourceDirectory directory is ${maven.project.build.sourceDirectory} </ echo >
< echo > Maven build outputDirectory directory is ${maven.project.build.outputDirectory} </ echo >
< echo > Maven build scriptSourceDirectory directory is ${maven.project.build.testSourceDirectory} </ echo >
< echo > Maven build testOutputDirectory directory is ${maven.project.build.testOutputDirectory} </ echo >
< echo > Maven build scriptSourceDirectory directory is ${maven.project.build.scriptSourceDirectory} </ echo >
< echo > Maven build resourceDirectory directory is ${maven.project.build.resources} </ echo >
< property name ="target.jar.name" value ="${maven.project.build.directory}/${maven.project.build.finalName}.jar" />
< echo > Maven build scriptSourceDirectory directory is ${target.jar.name} </ echo >
</ target >
< target name ="clean" depends ="init_maven" >
< echo > clean build directory : ${maven.project.build.directory} </ echo >
< delete dir ="${maven.project.build.directory}" includes ="**/*" />
</ target >
< target name ="init_path" depends ="maven_info, clean" >
< echo > make dir for java compile: ${maven.project.build.outputDirectory} </ echo >
< mkdir dir ="${maven.project.build.outputDirectory}" />
</ target >
< target name ="compile" description ="description" depends ="init_maven" >
< javac srcdir ="${maven.project.build.sourceDirectory}" destdir ="${maven.project.build.outputDirectory}" classpathref ="classpath.build" />
</ target >
< target name ="copyResource" depends ="init_maven" >
< copy todir ="${maven.project.build.outputDirectory}" >
< fileset dir ="src/main/resources" >
</ fileset >
</ copy >
</ target >
< target name ="jar" depends ="compile, copyResource" >
< delete file ="${maven.project.build.directory}/${maven.project.build.finalName}.jar" failonerror ="false" />
< jar destfile ="${maven.project.build.directory}/${maven.project.build.finalName}.jar" basedir ="${maven.project.build.outputDirectory}" >
</ jar >
</ target >
< target name ="package" depends ="package_prepare, copyLib, copyConfig, copyBin" >
</ target >
< target name ="package_prepare" depends ="init_maven" >
< echo > clean package directory : ${maven.project.build.directory}/${path.package} </ echo >
< delete dir ="${maven.project.build.directory}/${path.package}" />
< mkdir dir ="${maven.project.build.directory}/${path.package}" />
< mkdir dir ="${maven.project.build.directory}/${path.package}/${path.target.name}" />
< mkdir dir ="${maven.project.build.directory}/${path.package}/${path.target.name}/${path.package.lib}" />
< mkdir dir ="${maven.project.build.directory}/${path.package}/${path.target.name}/${path.package.config}" />
< mkdir dir ="${maven.project.build.directory}/${path.package}/${path.target.name}/${path.package.log}" />
</ target >
< target name ="copyLib" depends ="init_maven" >
< copy todir ="${maven.project.build.directory}/${path.package}/${path.target.name}/${path.package.lib}" >
< fileset refid ="maven.fileset.runtime" />
< mapper type ="flatten" />
</ copy >
< copy todir ="${maven.project.build.directory}/${path.package}/${path.target.name}/${path.package.lib}"
file ="${maven.project.build.directory}/${maven.project.build.finalName}.jar" >
</ copy >
</ target >
< target name ="copyConfig" depends ="init_maven" >
< copy todir ="${maven.project.build.directory}/${path.package}/${path.target.name}/${path.package.config}" >
< fileset dir ="src/main/config" >
</ fileset >
</ copy >
</ target >
< target name ="copyBin" depends ="init_maven" >
< copy todir ="${maven.project.build.directory}/${path.package}/${path.target.name}/${path.package.bin}" >
< fileset dir ="src/main/bin" >
</ fileset >
</ copy >
</ target >
< target name ="zip" depends ="init_maven" >
< zip destfile ="${maven.project.build.directory}/${path.package}/${path.target.name}.zip" >
< fileset dir ="${maven.project.build.directory}/${path.package}/${path.target.name}" ></ fileset >
</ zip >
</ target >
</ project >
一步一步来讲吧:
3.1 最重要的一步,init_maven
<!--
remember to set M2_REPO before use this build.xml, for example in eclispe:
"Window→Preferences→Ant→Runtime", add a new property named "M2_REPO" and set it value point to the path of your maven
local repository; Or you can set it in build.properties. You need do one (and only one) of them.
-->
< path id ="maven-ant-tasks.classpath" path ="${M2_REPO}/org/apache/maven/maven-ant-tasks/2.0.9/maven-ant-tasks-2.0.9.jar" />
< typedef resource ="org/apache/maven/artifact/ant/antlib.xml" uri ="urn:maven-artifact-ant" classpathref ="maven-ant-tasks.classpath" />
< artifact:pom id ="maven.project" file ="pom.xml" />
< artifact:dependencies pathId ="classpath.build" filesetid ="maven.fileset.build" >
< pom refid ="maven.project" />
</ artifact:dependencies >
< artifact:dependencies pathId ="classpath.runtime" filesetid ="maven.fileset.runtime" useScope ="runtime" >
< pom refid ="maven.project" />
</ artifact:dependencies >
</ target >
在ant中使用maven-ant-tasks,就需要装载maven-ant-tasks的jar包,方法有两种,一种是直接将maven-ant-tasks-2.0.9.jar放到ant的lib下,自然就可以直接使用。但是个人感觉不怎么喜欢这种方式,我采用的是第二种,在ant的build.xml文件中装载:
< typedef resource ="org/apache/maven/artifact/ant/antlib.xml" uri ="urn:maven-artifact-ant" classpathref ="maven-ant-tasks.classpath" />
这样就可以在后面使用maven-ant-tasks的task,比如artifact:pom,artifact: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/artifact/org.apache.maven/maven-ant-tasks
pom内容如下:
< groupId > org.apache.maven </ groupId >
< artifactId > maven-ant-tasks </ artifactId >
< 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后,接着是调用artifact:pom和artifact:dependencies 任务来指定pom.xml文件,再得到dependencies信息,后面的编译打包会使用到。注意useScope="runtime",这个是为了最后打包时使用,只复制runtie时需要的jar包。
<target name="maven_info" />是用来打印maven相关的一些信息的,比如maven下的几个build目录。artifact: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/introduction/introduction-to-the-pom.html
标准目录布局可以参考这个官方资料:
http://maven.apache.org/guides/introduction/introduction-to-the-standard-directory-layout.html
3.2 compile
这里是maven ant task的精髓所在,
< javac srcdir ="${maven.project.build.sourceDirectory}" destdir ="${maven.project.build.outputDirectory}" classpathref ="classpath.build" />
</ target >
结合之前maven初始化时的情况:
< artifact:dependencies pathId ="classpath.build" filesetid ="maven.fileset.build" >
< pom refid ="maven.project" />
</ artifact:dependencies >
可以看到,我们的项目完全遵循maven的标准做法,然后ant通过访问pom来得到相关的路径信息和classpath信息,完美结合。
target copyResource 完成了将resource copy到outputDirectory的任务,这里的resource都是classpath resource。
注: 这个有个问题,就是我没有找到通过pom得到resouce目录的方法,${maven.project.build.resources 只能得到pom文件中<resources/>, 对于里面包含的<resource>不知道该用什么方式来访问,如默认的:
< resource >
< directory > src/main/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/main/resources吧。
3.3 jar
和compile类似,标准的ant jar,然后通过访问pom来得到相关的路径信息和打包文件名。注意这里的文件名和路径和maven的做法一致,也就是说和执行maven的compile命令结果是一样的。
< delete file ="${maven.project.build.directory}/${maven.project.build.finalName}.jar" failonerror ="false" />
< jar destfile ="${maven.project.build.directory}/${maven.project.build.finalName}.jar" basedir ="${maven.project.build.outputDirectory}" >
</ jar >
</ target >
3.4 package, zip
package_prepare, copyLib, copyConfig, c
发表评论
-
搜索maven依赖的网站推荐
2011-12-02 16:04 4305使用maven填写依赖的时候,常会遇到需要查一下gro ... -
hudson中subversion HEAD check out 的问题及疑惑
2010-09-30 10:56 40近期发现一个问题,hudson执行任务时,经常不能获取 ... -
你走你的阳光道,我走我的独木桥:整合ant ivy 和testng
2010-05-31 16:11 2069近期自己折腾自己,放着正统的maven + jun ... -
slf4j1.6.0-RC0和logback的0.9.20版本不兼容
2010-04-26 08:54 3508今天,尝试使用slf4j + logback的黄金组合,结果发 ... -
fisheye2.2.1 & Crucible 2.2.1 安装配置笔记
2010-04-27 16:48 31771) 下载 从atlassian网站 ... -
让ivy支持maven的classifier属性
2009-10-15 01:56 3179在maven中,对于一个依赖,除了groupId,ar ... -
ivy教程(1)-目录
2009-09-21 23:57 2941学习的最佳方式是实践!这是ivy教程将帮助你做到的 ... -
ivy教程(2)-快速开始
2009-09-22 11:48 3052在这个例子中,我们将看到使用ivy的一个最简单的方 ... -
ivy教程(3)-调整默认设置
2009-09-24 20:58 2345ivy绑定一些默认 ... -
ivy教程(4)-多解析器
2009-09-25 15:28 1790这个例子演示模块是如何被多解析器获得的。使用多解析 ... -
ivy教程(5)-双重解析器
2009-09-27 20:58 1710在一些情况下,会发生这样的事情:你的模块描述符(ivy ... -
ivy教程(6)-项目依赖
2009-09-29 23:32 2999这个示例将举例说明在两个项目之间的依赖。 depen ... -
ivy教程(7)-在多项目环境下使用ivy
2009-10-03 11:48 2361在上一个教程中,你已 ... -
ivy教程(8)-使用ivy模块配置
2009-10-04 10:15 2659这个教程介绍ivy文件中的模块配置的使用。ivy模块配置事实上 ... -
ivy教程(9)-架设仓库(1)-介绍
2009-10-04 13:42 1846install任务让你从一个仓库复制一个模块或者模 ... -
ivy教程(10)-架设仓库(2)-基础仓库复制
2009-10-04 15:04 3050在这个步骤中我们使用install任务来从mave ... -
ivy教程(11)-架设仓库(3)-使用命名空间
2009-10-09 21:04 2251现在你已经看到从一个已经存在的仓库创建你自己的仓库是如何的简单 ... -
ivy教程(12)-更多例子
2009-10-09 21:29 1815如果你已经成功的跟随并理解了所有的教程,可能你还是需要得到更好 ... -
ivy中文参考文档(21)-ant任务(9)-post resolve tasks
2009-09-15 14:17 14641) post resolve tasks ... -
ivy中文参考文档(20)-ant任务(8)-cachefileset
2009-09-03 23:11 13891) cachefileset 为配置构建一个有iv ...
相关推荐
Ant是Apache软件基金会开发的一款Java项目构建工具,...通过阅读“ant使用手册(中文教程)”,无论是初学者还是有经验的开发者,都能深入理解Ant的工作原理和使用技巧,从而更好地在Java项目中运用Ant进行自动化构建。
本指南将针对初学者,详细介绍Ant的基本概念、安装、配置以及常用任务的使用。 一、Ant简介 Ant的设计理念是“简单就是美”。在Java开发中,当项目变得复杂时,手动管理编译、测试和部署等过程会变得繁琐,Ant则能...
Apache Ant 是一个广泛使用的Java构建工具,它允许开发者通过XML配置文件定义构建任务,从而自动化项目的构建、测试和部署过程。...对于初学者或小型项目来说,直接解压使用Ant 1.6.2是一个快速上手的途径。
Ant是Apache软件基金会下的一个Java项目,它是一个构建工具,主要用来自动化Java应用程序的构建过程。...这份“Ant使用指南”将深入浅出地讲解Ant的各种特性和用法,无论是初学者还是经验丰富的开发者,都能从中获益。
3. **持续集成环境**:Maven与持续集成工具(如Jenkins)结合使用,能够实现自动化构建和部署。 #### 六、Maven的扩展性 Maven的强大之处在于其高度可扩展性。用户可以根据自己的需求编写自定义插件或修改现有的...
Apache Ant 是一个广泛使用的Java构建工具,它允许开发者通过XML配置文件定义构建任务,从而自动化项目的编译、打包、测试等过程。Ant 的版本1.10.3是该工具的一个稳定版本,提供了许多增强的功能和修复的bug,使得...
Ant自动打包SDK脚本是Java开发中常用的一种自动化构建工具,它基于Apache Ant,一个用Java编写的构建工具,能够帮助开发者实现项目的编译、测试、打包和部署等一系列任务的自动化。这个脚本专为SDK开发者设计,可以...
Ant是Apache软件基金会的一个开源项目,它是一款Java构建工具,主要负责自动化构建Java项目,如编译源代码、运行测试、打包和部署等任务。Ant以其XML格式的构建文件(build.xml)闻名,使得构建过程可配置且可重复...
例如,ivy插件用于依赖管理,maven-ant-tasks则能实现与Maven的集成。 七、ANT与持续集成 ANT的可定制性和灵活性使其成为许多持续集成工具(如Jenkins、Hudson)的首选构建工具,能够自动化构建、测试和部署过程。 ...
这个压缩包文件集合提供了一系列关于Ant的学习资料,对于初学者来说是非常宝贵的资源。以下将详细阐述Ant的相关知识点。 1. **Ant简介** Ant是一个基于Java的构建工具,它的设计目标是简化Java项目构建过程,通过...
通过这个视频和项目,你将能够从零开始,逐步掌握Ant的使用,实现Java项目的构建、打包和部署。无论你是初学者还是有经验的开发者,这个资源都将帮助你更好地理解和运用Ant这一强大的构建工具。
对于初学者来说,掌握Ant的基本概念和使用方法是非常重要的。 一、Ant基本概念 1. 构建文件:在Ant中,构建过程是通过一个名为`build.xml`的XML文件来描述的,这个文件包含了所有的构建任务和目标。 2. 目标...
- **Ant贡献的任务**:许多第三方库提供了额外的任务,如Maven Ant Tasks用于Maven与Ant的集成。 - **Ant的Eclipse插件**:提供图形化界面,方便编辑和运行Ant构建。 9. **使用场景** - 自动构建Java项目 - ...
- Ant还可以通过扩展机制加载自定义的任务类,实现更复杂的功能。 7. **Ant与版本控制系统的集成** - Ant可以轻松地与Git、SVN等版本控制系统结合,进行版本库操作,如获取最新代码、提交等。 8. **Ant与Maven的...
在软件开发过程中,Ant主要负责编译、打包、测试等自动化任务,极大地提升了开发效率和项目的可维护性。它采用XML来定义任务,使得构建过程具有良好的可读性和可移植性。 Ant的核心概念是“构建文件”(build.xml)...
虽然Maven后来成为另一种流行的Java构建工具,但Ant因其简单性和灵活性仍然被广泛使用。Maven使用约定优于配置的方式,而Ant则是完全自定义配置。 9. 综合应用: 在实际开发中,开发者通常会结合Ant与其他工具,...
还可以通过Ant本身提供的task或者第三方库与Maven、Gradle等现代构建工具交互。这些工具的集成大大提升了Ant的实用性。 Ant的文件操作功能也非常强大,包括复制、移动、删除、重命名等,同时支持文件集(filesets)...
Apache Ant 是一个由Java...这个例子将帮助初学者理解Ant的基本结构和命令行界面,以及如何在实际项目中使用Ant进行构建。通过分析和运行这个"Hello World"项目,你可以快速上手Ant,为进一步深入学习和应用打下基础。
**Ant使用指南** Apache Ant,一个Java库和命令行工具,其任务是驱动构建过程。它是Java开发中的一个重要工具,特别是在Maven和Gradle流行之前,Ant是许多Java项目的首选构建系统。Ant基于XML,允许开发者定义构建...
1. Jenkins、Maven和Gradle:Ant常与其他持续集成工具如Jenkins配合使用,虽然Maven和Gradle逐渐流行,但Ant在某些场景下仍有其优势。 2. Ivy:Ivy是Ant的依赖管理插件,可以方便地管理和解决项目依赖问题。 七、...