首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 其他教程 > 开源软件 >

关于运用ant制作可执行jar

2012-07-05 
关于使用ant制作可执行jar?? 由于部署的需要,需要将业务实现打成可执行jar部署在linux上长期运行。一般说,

关于使用ant制作可执行jar

?? 由于部署的需要,需要将业务实现打成可执行jar部署在linux上长期运行。一般说,用Eclipse导出jar即可,他会把依赖的jar一起打到我们的最终jar中,这个过程是手动的-----对于我习惯于使用自动化时,这就让我不爽了,且:使用eclipse导出的可执行jar,eclipse本身会在里面加一些属于自己的东西, 不信你可以看看 jarFile/META-INF/MANIFEST.MF就知道了,其中加了一些属于eclipse的jar,包括启动类也是eclipse的, 实际上我的jar已经依赖够多了,这也是我不能容忍的地方,因此,我简单的拓展了下ant 任务,使用自定义任务结合 ant 的 jar任务,一起打可执行包。

?? 关于制作可执行jar有几种方式,不清楚的地方可以参考这篇博客
?? http://yangdc.iteye.com/blog/144507?

??
? 好了,有了上面的基础知识后,我们对比一下就知道第三种方式最适合,因为这样我们可以在应用程序级别上管理我们应用的依赖lib。 其核心思想就是 在清单文件中指定类路径,这样的话我们即可在将引用的jar 单独放在某个目录,只需在打包的适合指定即可。
但是第三种方式也有个缺点,如果你引用的jar比较多,那么你不得不写很长很长的路径,如: Class-Path:classes12.jar? lib/class12.jar....................
或者聪明一点的是写个小程序去遍历classpath吧,但是如果处于调试阶段,你将重复的去制作清单文件,打包。。。。。。烦死了。
?
?
? 下面的内容需要一定的ant基础。

????? 制作可执行jar一个比较重要的任务就是 在清单文件中指定启动类(Main-Class)和Class-Path属性,这样的话在执行jar的适合,JVM就知道从什么地方加载、哪个类是入口类----执行才为可能。
?????
????? ant的jar 任务可以在订单文件中写入各种属性,其中Main-Class可以我们手动指定, 而Class-Path手动指定就太麻烦了。? 由于jar引用的classpath是确定,且jar任务可以写入任何清单属性,那么,我们能不能将classpath生成然后借助jar任务写入清单文件件呢?

????? 上面就是基本原理,废话少说(已经说了很多啦), 下面是如何拓展ant任务。

????? Task的参数
????? classpath: 类路径Path类,需要将这path代表的jar的名称写入清单中
????? outClassPath:通过任务生成的Class-Path,这个值实际上是一个属性的key值,
????????????????????? 可以通过引用这个key 得到task生成的类路径列表。
????? libPath? :? 这个是生成在每一个jar前面的根路径,通过指定这个值,
???????????????????? 可以控制最终生成可执行jar的目录中引用lib的位置已经文件件名称。?

? 再看看如何拓展ant任务。

?

??

public class BuildClassPathTask extends Task {

?private String outClassPath;

?private Path classpath;

?private String libPath;

?@Override
?public void execute() throws BuildException {

??super.execute();

??if (null == outClassPath || "".equals(outClassPath.trim())) {
???throw new BuildException("outClassPath could not be null!");

??}
??if (null == classpath) {
???throw new BuildException("classpath could not be null!");
??}

??String[] all = classpath.list();

??StringBuilder sb = new StringBuilder();

??if (null == libPath || "".equals(libPath)) {
???libPath = "";
??}

??libPath += "/";

??for (int i = 0; i < all.length; i++) {

???String filePath = all[i];
???filePath = filePath.substring(1 + filePath.lastIndexOf(System
?????.getProperty("file.separator")));
???sb.append(libPath);
???sb.append(filePath);
???sb.append(" "); // one blank
??}
??sb.append(System.getProperty("line.separator"));
??System.out.println("execute :? " + sb.toString());

??PropertyHelper ph = PropertyHelper.getPropertyHelper(getProject());
??ph.setNewProperty(outClassPath, sb.toString());

?}

?public String getOutClassPath() {
??return outClassPath;
?}

?public void setOutClassPath(String outClassPath) {
??this.outClassPath = outClassPath;
?}

?public Path createClasspath() {
??if (classpath == null) {
???classpath = new Path(getProject());
??}
??return classpath.createPath();
?}

?public void setClasspath(Path classpath) {
??this.classpath.append(classpath);
?}

?public Path getClasspath() {
??return classpath;
?}

?public String getLibPath() {
??return libPath;
?}

?public void setLibPath(String libPath) {
??this.libPath = libPath;
?}

?

? 上面的代码简单的说就是: 我有一个引用lib,通过这个Task 生成一个jar清单格式的Class_Path,然后将这个拼装好的路径放在Ant的上下文属性中,你可以在jar中引用这个属性,并最终写入你的jar的清单文件中。

?? 我们将上面的Task编译打包然后放在ant的lib目录下去,这样就成了我的工具的一部分了,这部分工作我使用的仍是ant,build.xml文件是:

?

<?xml version="1.0"?>
<project default="main" basedir=".">
?<property name="source" value="src/com/" />
?<property name="classes" value="build/classes" />
?<property name="jar.path" value="build/jar" />
?<property name="jar.name" value="deftask.jar" />

?<delete dir="${classes}" />
?<mkdir dir="${classes}" />

?<target name="main">
??<javac srcdir="${source}" destdir="${classes}">
??</javac>
??<jar destfile="${jar.path}/${jar.name}" basedir="${classes}" update="true" />
??<copy tofile="${ant.home}/lib/${jar.name}" file="${jar.path}/${jar.name}" overwrite="true" />
?</target>
</project>



??? 执行上面的ant后,这个任务就部署在 ANT_HOME/lib目录下了,以后可以随意使用了。

现在看如何使用它:

??? 在编译打包我的目标应用程序时,使用的ant,部分代码如下:

?

<javac srcdir="${sources}" destdir="${destDir}">
???<classpath>
????<fileset dir="lib" includes="*.jar">
????</fileset>
???</classpath>
??</javac>

??<taskdef name="buildClassPath" classname="com.taoyu.ant.excutable.jar.BuildClassPathTask">
???<classpath>
????<fileset dir="${ant.home}/lib" includes="*.jar" />
???</classpath>
??</taskdef>

??<buildClassPath libpath="lib" outclasspath="manifest_class">
???<classpath>
????<fileset dir="lib" includes="**/*.jar" />
???</classpath>
??</buildClassPath>

??<jar destfile="${build}/${jarFileName}" basedir="${destDir}" update="true">
???<manifest>
????<attribute name="Main-Class" value="com.rockton.syn.task.Laungher" />
???</manifest>
???<manifest>
????<attribute name="Class-Path" value="${manifest_class}" />
???</manifest>
??</jar>

??<echo message="jar file over" />

??<ftp action="send" server="192.168.1.6" userid="root" password="ytsj" remotedir="/root/userfile/yutao/synDataTool/lib">
???<fileset dir="lib" />
??</ftp>




? 上面是: 编译-->声明自定义任务---->生成路径串-->打包--->部署到环境


好了,整个过程就这么个过程,如果有帮助到你我很荣幸,如果需要帮助,请留言。QQQ!


关于那个 libPath的作用可以用下图了解释:

??? dir(d://test)
??? ------DataSynTool.jar (那个可执行jar)
??? ------lib(所以引用的第三方jar包) libPath=lib? 你现在应该明白什么意思了

附件是ant任务定义工程, 下载解压后可以直接导入你的eclipse中。

?

热点排行