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拉倒的冲动。
先交代一下背景吧,我要打包的程序,是这个样子:
1
2
3
4
5
6
7
8
9
10
11
12
|
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的推荐,文件结构如下:
1
2
3
4
5
6
7
8
9
10
11
|
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,标准内容,很简单,象征性的加入几个依赖
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
<dependency>
<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
1
2
3
4
5
6
|
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,这个内容比较多。
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
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
|
<?xmlversion=
"1.0" encoding=
"UTF-8" ?> <projectname=
"demo" default
= "all"
xmlns:artifact= "urn:maven-artifact-ant"
> <description>
</description>
<propertyfile=
"build.properties" />
<targetname=
"init_maven" > <!-- remembertosetM2_REPObeforeusethisbuild.xml,forexampleineclispe:
"Window→Preferences→Ant→Runtime" ,addanewpropertynamed
"M2_REPO" andsetitvaluepointtothepathofyourmaven
localrepository;Oryoucansetitinbuild.properties. Youneeddoone(andonlyone)ofthem.
--> <pathid=
"maven-ant-tasks.classpath"
path= "${M2_REPO}/org/apache/maven/maven-ant-tasks/2.0.9/maven-ant-tasks-2.0.9.jar"
/> <typedefresource=
"org/apache/maven/artifact/ant/antlib.xml"
uri= "urn:maven-artifact-ant"
classpathref= "maven-ant-tasks.classpath"
/> <artifact:pomid=
"maven.project" file=
"pom.xml" /> <artifact:dependenciespathId=
"classpath.build" filesetid=
"maven.fileset.build" >
<pomrefid=
"maven.project" />
</artifact:dependencies>
<artifact:dependenciespathId=
"classpath.runtime" filesetid=
"maven.fileset.runtime"
useScope= "runtime"
> <pomrefid=
"maven.project" />
</artifact:dependencies>
</target>
<targetname=
"all" depends=
"init_path,compile,jar,package,zip" description=
"doall" > <echo>begintodoalltargettobuildtheresultpackage.</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}"
includes= "**/*"
/> </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}"
classpathref= "classpath.build"
/> </target>
<targetname=
"copyResource" depends=
"init_maven" > <copytodir=
"${maven.project.build.outputDirectory}"
> <filesetdir=
"src/main/resources" >
</fileset>
</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}"
> <filesetrefid=
"maven.fileset.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}"
> <filesetdir=
"src/main/config" >
</fileset>
</copy>
</target>
<targetname=
"copyBin" depends=
"init_maven" > <copytodir=
"${maven.project.build.directory}/${path.package}/${path.target.name}/${path.package.bin}"
> <filesetdir=
"src/main/bin" >
</fileset>
</copy>
</target>
<targetname=
"zip" depends=
"init_maven" > <zipdestfile=
"${maven.project.build.directory}/${path.package}/${path.target.name}.zip"
> <filesetdir=
"${maven.project.build.directory}/${path.package}/${path.target.name}"
></fileset> </zip>
</target>
</project>
|