使用ant生成可执行的jar包

时间:2020-12-23 09:17:12

1. a.下载ant: http://ant.apache.org/bindownload.cgi

    b.安装ant: 解压ant,路径越简单越好(这是好习惯),设置环境变量ANT_HOME,PATH里添加;%ANT_HOME%\bin

    c.打开cmd,键入ant回车,如果出现提示信息
"Buildfile: build.xml does not exist!
Build failed"
就说明安装成功了


2.  java工程目录结构:
|-src-|-  //.java源文件
|-bin-|- // .class文件
|-lib-|-  //第三方jar包
build.xml    // ant 配置文件

 

3。由于ant没有提供填写jar包里Class-Path的任务,所以需要编写自定义任务,扩展Ant,Java代码如下:

Java代码 使用ant生成可执行的jar包 使用ant生成可执行的jar包使用ant生成可执行的jar包
  1. package personal.lw.util;    
  2.   
  3. import java.io.File;    
  4.   
  5. import org.apache.tools.ant.BuildException;    
  6. import org.apache.tools.ant.Task;    
  7.   
  8. public class AntUtil extends Task {    
  9.   
  10.     private String lib;    
  11.   
  12.     private String classPath = "";    
  13.   
  14.     private String fileType = ".jar";    
  15.   
  16.     // ant task    
  17.     public void execute() throws BuildException {    
  18.         try {    
  19.             this.classPath(dir(lib));    
  20.             this.getOwningTarget().getProject().setProperty("class-path",    
  21.                     classPath);    
  22.         } catch (Exception e) {    
  23.             e.printStackTrace();    
  24.         }    
  25.   
  26.     }    
  27.   
  28.     // 根据路径获得目录    
  29.     private File dir(String path) throws Exception {    
  30.         return dir(path, false);    
  31.     }    
  32.   
  33.     private File dir(String path, boolean bCreate) throws Exception {    
  34.         File dir = new File(path);    
  35.         if (dir.exists()) {    
  36.             if (!dir.isDirectory()) {    
  37.                 throw new Exception(dir.getName() + "is not a directory !");    
  38.             }    
  39.         } else {    
  40.             if (bCreate) { // 新建   
  41.                 if (!dir.mkdirs()) {    
  42.                     throw new Exception("can not create the directory \""    
  43.                             + dir.getName() + "\"!");    
  44.                 }    
  45.             }    
  46.         }    
  47.         return dir;    
  48.     }    
  49.   
  50.     // 生成classpath字符串    
  51.     private void classPath(File dir) {    
  52.         classPath(dir, lib);    
  53.         classPath = classPath.trim();    
  54.     }    
  55.   
  56.     private void classPath(File dir, String parentPath) {    
  57.         // 处理目录    
  58.         if (dir.isDirectory()) {    
  59.             File[] subs = dir.listFiles();    
  60.             for (int i = 0, len = subs.length; i < len; i++) {    
  61.                 if (subs[i].isFile()) { // 文件   
  62.                     String name = subs[i].getName();    
  63.                     // 处理.jar文件    
  64.                     if (name.length() > fileType.length()    
  65.                             && fileType.equals(name.substring(name.length()    
  66.                                     - fileType.length(), name.length()))) {    
  67.                         classPath += parentPath + path(subs[i]) + " ";    
  68.                         continue;    
  69.                     }    
  70.                 }    
  71.                 if (subs[i].isDirectory()) { // 文件夹   
  72.                     classPath(subs[i], parentPath + path(subs[i]));    
  73.                 }    
  74.             }    
  75.   
  76.         } else {    
  77.             // 不是目录    
  78.             System.out.println(dir.getPath() + dir.getName()    
  79.                     + "is not a directory !");    
  80.         }    
  81.     }    
  82.   
  83.     // 文件路径    
  84.     private String path(File f) {    
  85.         return "/" + f.getName();    
  86.     }    
  87.   
  88.     // 字符串 -- > 路径    
  89.     @SuppressWarnings("unused")    
  90.     private String path(String path) {    
  91.         path = path.replaceAll("\\\\", "/");    
  92.         if (!"/".equals(path.substring(01))) {    
  93.             path = "/" + path;    
  94.         }    
  95.         return path;    
  96.     }    
  97.   
  98.     public void setLib(String lib) {    
  99.         this.lib = lib;    
  100.     }    
  101.   
  102. }   
  103.   
  104.   
  105. 本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/liuwei_blog/archive/2008/12/20/3567292.aspx  

 编译后打成jar包,拷贝到%ANT_HOME%\lib目录下,注意编译的时候需要导入ant的jar包,如果用ant打包就不需要导ant的jar包了,生成普通jar包的ant配置文件如下:

Xml代码 使用ant生成可执行的jar包 使用ant生成可执行的jar包使用ant生成可执行的jar包
  1. <?xml version="1.0" encoding="GB2312" standalone="no"?>    
  2. <project basedir="." default="usage" name="hibernate"> <!-- ====此处需要修改====工程名 -->    
  3. <!-- 工程名,没有被引用,可以不改 -->    
  4.       <property name="project-name" value="hibernate"/> <!-- ====此处需要修改====.jar文件名 -->    
  5.       <property name="lib" value="lib"/> <!-- lib-->    
  6.       <property name="src" value="src"/> <!-- src-->    
  7.       <property name="tar" value="bin"/> <!-- bin -->    
  8.       <property name="jar-file-name" value="${project-name}.jar"/>    
  9.       <property name="main-class" value="demo.book.controler.Test"/> <!-- ====此处需要修改====main-class-->    
  10.   
  11.       <path id="Third-Part Lib">    
  12.             <fileset dir="${lib}">    
  13.                   <include name="**/*.jar"/>    
  14.             </fileset>    
  15.       </path>    
  16.   
  17.       <target description="Build file usage info (default task)" name="usage">    
  18.             <echo message=" "/>    
  19.             <echo message="  ${project-name} "/>    
  20.             <echo message="-------------------------------------------------------"/>    
  21.             <echo message="  Available Targets:"/>    
  22.             <echo message="  compile    - Compiles the source code"/>    
  23.             <echo message="  clean      - Delete class files and .jar file"/>    
  24.             <echo message="  jar        - Generate an .jar for source code"/>    
  25.             <echo message="  run        - Execute Main-Class"/>    
  26.             <echo message="-------------------------------------------------------"/>    
  27.       </target>    
  28.   
  29.       <target name="prepare">    
  30.             <mkdir dir="${tar}"/>    
  31.       </target>    
  32.   
  33.       <target name="clean">    
  34.             <delete dir="${tar}"/>    
  35.             <delete file="${jar-file-name}"/>    
  36.       </target>    
  37.         
  38.     <target name="copy-res">    
  39.         <copy todir="${tar}">    
  40.             <fileset dir="${src}">    
  41.                 <exclude name="**/*.java"/>    
  42.             </fileset>    
  43.         </copy>    
  44.     </target>    
  45.   
  46.       <target depends="clean,prepare,copy-res" name="compile">    
  47.             <javac debug="true" deprecation="true" destdir="${tar}" failonerror="true" srcdir="${src}">    
  48.                   <classpath refid="Third-Part Lib"/>     
  49.             </javac>    
  50.       </target>    
  51.       <!--    
  52.        <target name="run" depends="jar">    
  53.             <java jar="${jar-file-name}" fork="true" maxmemory="256m"/>    
  54.       </target>    
  55.   
  56.       -->    
  57.         <!-- 注意:classpath="${tar}" 一定要加上,否则会报"java.lang.NoClassDefFoundError"的错误!-->    
  58.         <target depends="compile" name="run">    
  59.             <java classname="${main-class}" classpath="${tar}" fork="true" maxmemory="256m">    
  60.                   <classpath refid="Third-Part Lib"/>     
  61.             </java>    
  62.       </target>    
  63.   
  64.       <target depends="compile" name="jar">    
  65.             <jar basedir="${tar}" destfile="${jar-file-name}">    
  66.                   <manifest>    
  67.                         <attribute name="Main-Class" value="${main-class}"/>    
  68.                         <attribute name="Class-Path" value=""/>    
  69.                   </manifest>    
  70.             </jar>    
  71.       </target>    
  72. </project>   
 

4.生成可执行jar包的ant配置文件如下:

Xml代码 使用ant生成可执行的jar包 使用ant生成可执行的jar包使用ant生成可执行的jar包
  1. <?xml version="1.0" encoding="GB2312" standalone="no"?>    
  2. <project basedir="." default="usage" name="hibernate"> <!-- ====此处需要修改====工程名 -->    
  3. <!-- 工程名,没有被引用,可以不改 -->    
  4.       <property name="project-name" value="hibernate"/> <!-- ====此处需要修改====.jar文件名 -->    
  5.       <property name="lib" value="lib"/> <!-- lib-->    
  6.       <property name="src" value="src"/> <!-- src-->    
  7.       <property name="tar" value="bin"/> <!-- bin -->    
  8.       <property name="jar-file-name" value="${project-name}.jar"/>    
  9.       <property name="main-class" value="demo.book.controler.Test"/> <!-- ====此处需要修改====main-class-->    
  10.   
  11.       <path id="Third-Part Lib">    
  12.             <fileset dir="${lib}">    
  13.                   <include name="**/*.jar"/>    
  14.             </fileset>    
  15.       </path>    
  16.   
  17.       <target description="Build file usage info (default task)" name="usage">    
  18.             <echo message=" "/>    
  19.             <echo message="  ${project-name} "/>    
  20.             <echo message="-------------------------------------------------------"/>    
  21.             <echo message="  Available Targets:"/>    
  22.             <echo message="  compile    - Compiles the source code"/>    
  23.             <echo message="  clean      - Delete class files and .jar file"/>    
  24.             <echo message="  jar        - Generate an .jar for source code"/>    
  25.             <echo message="  run        - Execute Main-Class"/>    
  26.             <echo message="-------------------------------------------------------"/>    
  27.       </target>    
  28.   
  29.       <target name="prepare">    
  30.             <mkdir dir="${tar}"/>    
  31.       </target>    
  32.   
  33.       <target name="clean">    
  34.             <delete dir="${tar}"/>    
  35.             <delete file="${jar-file-name}"/>    
  36.       </target>    
  37.         
  38.     <target name="copy-res">    
  39.         <copy todir="${tar}">    
  40.             <fileset dir="${src}">    
  41.                 <exclude name="**/*.java"/>    
  42.             </fileset>    
  43.         </copy>    
  44.     </target>    
  45.   
  46.       <target depends="clean,prepare,copy-res" name="compile">    
  47.             <javac debug="true" deprecation="true" destdir="${tar}" failonerror="true" srcdir="${src}">    
  48.                   <classpath refid="Third-Part Lib"/>     
  49.             </javac>    
  50.       </target>    
  51.       <!--    
  52.        <target name="run" depends="jar">    
  53.             <java jar="${jar-file-name}" fork="true" maxmemory="256m"/>    
  54.       </target>    
  55.   
  56.       -->    
  57.         <!-- 注意:classpath="${tar}" 一定要加上,否则会报"java.lang.NoClassDefFoundError"的错误!-->    
  58.         <target depends="compile" name="run">    
  59.             <java classname="${main-class}" classpath="${tar}" fork="true" maxmemory="256m">    
  60.                   <classpath refid="Third-Part Lib"/>     
  61.             </java>    
  62.       </target>    
  63.       <!-- 自定义任务,创建并赋值变量class-path -->    
  64.       <taskdef name="jarcp" classname="personal.lw.util.AntUtil"/>    
  65.       <target name="class-path">    
  66.         <jarcp lib="${lib}"/>    
  67.       </target>    
  68.   
  69.       <target depends="compile,class-path" name="jar">    
  70.             <jar basedir="${tar}" destfile="${jar-file-name}">    
  71.                   <manifest>    
  72.                         <attribute name="Main-Class" value="${main-class}"/>    
  73.                         <attribute name="Class-Path" value="${class-path}"/>    
  74.                   </manifest>    
  75.             </jar>    
  76.       </target>    
  77. </project>   
 

只比上一个多了一个自定义任务。

 

(完) ^_^



Ant自带了大量的任务(Task),在网上也有大量的任务可用,可是如果你面对的是别人根本不会想到的问题,怎么办呢?其实,只要花一点点功夫就可以编写出自己的任务出来。我开始也没想到会这样简单(做嵌套任务碰到一点问题),由此可见Ant的结构设计是相当优秀的。

 

假设我们需要显示任务执行各花了多少时间,写一个TimerTask

 

起步:覆盖org.apache.tools.ant.Task的execute方法

 

import org.apache.tools.ant.Task;

import org.apache.tools.ant.BuildException;

 

 

publicclass TimerTask extends Task {

publicvoid execute() throws BuildException {

    System.out.println("I am a timer");

}

}

注意,编译时ant.jar必须在Classpath上。

简单起见,假设Java源文件,类文件在同一目录下,在此目录再写一个build.XML文件:

<?xml version="1.0" ?>

<projectname="testTimer"default="test" basedir=".">

<taskdefname="timer" classname="TimerTask" classpath="."/>

 

<targetname="test">

    <timer/>

</target>

</project>

 

打开Dos窗口,到此目录,运行ant

够简单吧!如果类路径比这复杂或者在jar文件中,设置<taskdef>的classpath属性就行了。

 

继续:设置属性

假设我们想添加一个action属性,在Java文件中:

private String action;

….

public void execute() throws BuildException {

if (action.equals(“init”)) {

        …

}

}

 

public String getAction() {

return action;

}

 

public void setAction(String string) {

action = string;

}

 

在xml文件中:

<timer action=”init” />

 

使用Project保存中间结果

对于这个任务来讲,必须把时间值保存起来,比较合适的就是org.apache.tools.ant.Project了,Project对象生命期是整个Build,并且可以通过setProperty, getProperty等方法保存/获取值。

 

publicvoid execute() throws BuildException {

    if (getOwningTarget() ==null)

        return;

    Project proj = getOwningTarget().getProject();

    …

    // can do smt with proj now

}

 

晋级:嵌套任务

如果我们想要在Timer下面再嵌套子任务(好像没有这个必要 :-):

<timer action=”init” >

<foo />

</timer>

 

那我们首先只需要写一个简单的FooTask,然后在build.xml加上<foo>的定义:

<taskdefname="timer" classname="TimerTask" classpath="."/>

<taskdefname="foo" classname="FooTask" classpath="."/> 

 

然后给TimerTask添加一个方法:

public void addFoo(FooTask foo) {

}

注意:addXXX的XXX由<taskdef>中的name决定,Ant会利用Java Reflection去找;类型必须是具体的类型FooTask,不能是Task。

结束:全部代码:

 

(问什么不能带附件?)

 

TimerTask.Java:

 

import java.util.*;

 

import org.apache.tools.ant.Task;

import org.apache.tools.ant.Project;

import org.apache.tools.ant.BuildException;

 

/**

 *TimerTask.java

 *<p>Copyright:Copyright (c)2003 你可以对本程序随意修改,复制,使用,但请保留这里注释声明!!!</p>

  *@author 李尚强blundblade@sina.com

 */

 

publicclass TimerTask extends Task {

private List fooList =new ArrayList();

private String action =""; //init, print

privatestatic final String TIME_PROPERTY_INTERNAL ="timer.msecs";

privatestatic final String TIME_PROPERTY_NAME ="timer.passed";

publicvoid execute() throws BuildException {

    System.out.println("I am a timer");

    System.out.println("but there are so many foos: " + fooList);

          

    if (this.getOwningTarget() ==null)

        return;

    Project proj = this.getOwningTarget().getProject();

    String strTime = proj.getProperty(TIME_PROPERTY_INTERNAL);

   

    try {

        long currMSecs = System.currentTimeMillis();

        if (action.equals("print")){

           if (strTime ==null)

               proj.setProperty(TIME_PROPERTY_NAME,"Timer not initilized");

           else {

               long startMSecs = Long.parseLong(strTime);

               long passedSecs = currMSecs - startMSecs;

               int minutes = (int) ( passedSecs * 1.0 / (1000 * 60 * 60) );

               int hours = minutes / 60;

               minutes = minutes % 60;

               strTime = hours + " hours " + minutes + " minutes";

               proj.setProperty(TIME_PROPERTY_NAME, strTime);

           }

        }

        elseif (action.equals("init")) {

           proj.setProperty(TIME_PROPERTY_INTERNAL, Long.toString(currMSecs));  

        }

       

    }

    catch (NumberFormatException nfe) {

        thrownew BuildException(nfe.getMessage());

    }

   

 

}

publicvoid addFoo(FooTask foo){

    fooList.add(foo);

}

/**

 *@return

 */

public String getAction() {

    return action;

}

 

/**

 *@param string

 */

publicvoid setAction(String string) {

    action = string;

}

 

}

FooTask.Java:

 

/*

 * Created on 2004-4-17

 *

 */

 

import org.apache.tools.ant.Task;

 

 

/**

 * FooTask.java

 * <p>Copyright: Copyright (c) 2003 你可以对本程序随意修改,复制,使用,但请保留这里注释声明!!!</p>

  * @author李尚强 blundblade@sina.com

 */

 

public class FooTask extends Task {

private String name ="";

/**

 * @return

 */

public String getName() {

    return name;

}

 

/**

 * @paramstring

 */

public void setName(String string) {

    name = string;

}

public String toString() {

    return name;

}

 

}

 

build.XML:

<?xml version="1.0" ?>

<project name="testTimer" default="test" basedir=".">

<taskdef name="timer" classname="TimerTask"classpath="."/>

<taskdef name="foo" classname="FooTask"classpath="."/>

 

<target name="test">

    <timer action="init">

        <foo name="F1" />

        <foo name="F2" />

        <foo name="F3" />

        <foo name="F4" />                            

    </timer>

   

    <!-- You can do some long-time work here -->

   

    <timer action="print" />

    <echo message="You have use time :${timer.passed}"/>

</target>

</project>