`
hain
  • 浏览: 457223 次
  • 来自: ...
社区版块
存档分类
最新评论

Apache Ant学习笔记之一

阅读更多

http://taylorblog.bokee.com/3458295.html

Apache Ant学习笔记之一

©原作者:Matt Chapman 

•Apache Ant源缘及目的

   Apache Ant 是一个基于 Java 的生成(在软件开发中用来将源代码和其他输入文件转换为可执行文件的形式)工具
   最初的创始人 James Duncan Davidson
   Ant=another neat tool
   Ant 最初是 Tomcat 的一个内部组件
   其第一个独立版本于 2000 年 7 月发布。

   它是为了解决:

 随着应用程序的生成过程变得更加复杂,确保在每次生成期间都使用精确相同的生成步骤,同时实现尽可能多的自动化,以便及时产生一致的生成版本,这就变得更加重要了。

Ant工具概要

    Ant 的生成文件是用 XML 编写的。每个生成文件由单个 project 元素组成,该元素又包含一个或多个 target 元素。
    顶级 project 元素需要包含一个 default 属性,如果在 Ant 被调用时没有指定目标,这个属性将指定要执行的目标。
    target是生成过程中已定义的一个步骤,它执行任意数量的操作。

    如下是一个最简单的文件:

<!---->
<project name="Project Argon" default="init"></project>
    <description></description>
    A simple project introducing the use of descriptive tags in Ant build files.
   
    <!---->

    <target description="Initialize Argon database" name="init"></target>
   

    需要说明的是:

    1.XML 声明指定了所使用的 XML 的版本,这不是当前的 Ant 所必需的
    2.一次性打开和关闭一个元素是允许的,如:<target name="init"></target>,当元素没有包含任何内容时,更简练的形式会更清晰。
    3.XML 注释可以使用在整个生成文件中以提高清晰性。而且,Ant 定义了它自己的 description 元素和 description 属性,它们可用于提供更结构化的注释。

应该了解的一些基本概念

属性

   可以这样定义属性:

<property name="metal" value="beryllium"></property>


   为了在生成文件的其他部分引用这个属性,要使用以下语法:

 ${metal}


   例如,为了使用这样一个值,它是另一个属性的值的组成部分,标签要写成下面这样:

   <property name="metal-database" value="${metal}.db"></property> <property name="metal-database" value="${metal}.db"></property>

   属性分为预定义属性和自定义属性:

   —预定义的属性:

   运行 Ant 的所有系统属性,均可作为 Ant 属性使用,如:
   ${user.home}

   —自定义属性:

   ${ant.version},这个属性包含 Ant 的版本;
   ${basedir},这个属性是项目目录的绝对路径(由包含生成文件的目录所定义,或者由 project 元素的可选 basedir 属性所定义)。

    Ant 的 location 属性专门设计用于以平台无关的方式包含文件系统路径。您会像下面这样使用 location 来代替value:

  <property name="database-file" location="archive/databases/${metal}.db"></property>

   在可能的地方使用相对路径名称而不是绝对路径名称,这样还会更加灵活。

定义依赖关系

    使用 target 元素的 depends 属性来实现,每个目标的定义依据的是在它在能够执行之前必须完成的其他所有目标。如:

 <target name="init"></target>
<target name="preprocess" depends="init"></target>
<target name="compile" depends="init,preprocess"></target>
<target name="package" depends="compile"></target>


    目标出现在生成文件中的顺序并不重要:执行顺序是由 depends 属性唯一确定的。

使用命令行来运行Ant

    如果你敲入Ant后回车,默认情况下Ant 寻找一个名为 build.xml 的文件来执行。
    Ant 使用 -buildfile <file></file>参数(-f <file></file>是其简写形式)你可以指定要执行的生成文件。

    -D选项用于设置随后可以在生成文件中使用的属性。

 例如,为了将 name 属性设置为某个特定的值,您会使用一个类似下面这样的选项:-Dmetal=beryllium

    这个功能可用于覆盖生成文件中的初始属性设置。正如前面指出过的,属性的值一经设置就不能改变。-D 标志在读取生成文件中的任何信息之前设置某个属性;由于生成文件中的指派落在这个初始指派之后,因此它不会改变其值。

编写常用的target

 Ant 的主要目标是生成 Java 应用程序,它能够内在地支持调用 javac 编译器以及其他 Java 相关任务。

编译 Java 代码的任务的编写方式:

 <javac srcdir="src"></javac>

    还支持的属性有:
       destdir:将类文件放在一个单独的目标目录
       classpath:等价于 javac 的 -classpath 选项。
       debug="true":指示编译器应该带调试信息编译源文件。
    javac 任务的一个重要特点在于,它仅编译那些它认为需要编译的源文件。如果某个类文件已经存在,并且对应的源文件自从该类文件生成以来还没有改变过,那么该源文件就不会被重新编译。

    编写一个 clean 目标来从目标目录移除生成的任何类文件是个很好的习惯。如果想要确保所有源文件都已编译,就可以使用这个任务。

    Ant 的 javac 任务的默认行为是调用运行 Ant 本身的任何 JVM 的标准编译器。然而,有时您可能想要单独地调用编译器 ―― 例如当你希望指定编译器的某些内存选项,或者需要使用一种不同级别的编译器的时候。为实现这个目的,只需将 javac 的 fork 属性设置为 true,比如像下面这样:

 <javac srcdir="src" fork="true"></javac>

    如果想要指定一个不同的 javac 可执行文件,并向它传递一个最大内存设置,您可以像下面这样做:
 <javac srcdir="src" fork="true" memorymaximumsize="128m" executable="d:\sdk141\bin\javac"></javac>

•创建 JAR 文件的任务的编写

 <jar basedir="classes" destfile="package.jar"></jar>

    这将创建一个名为 package.jar 的 JAR 文件,并把 classes 目录中的所有文件添加到其中(JAR 文件能够包含任意类型的文件,而不只是类文件)。此处没有指定清单文件,因此 Ant 将提供一个基本的清单文件。如:

 <jar basedir="classes" destfile="package.jar"></jar>
  <manifest></manifest>
    <attribute name="Built-By" value="${user.name}"></attribute>
    <attribute name="Main-class" value="package.Main"></attribute>
 

•时间戳生成:

    在生成环境中使用当前时间和日期,以某种方式标记某个生成任务的输出,以便记录它是何时生成的,这经常是可取的。这可能涉及编辑一个文件,以便插入一个字符串来指定日期和时间,或将这个信息合并到 JAR 或 zip 文件的文件名中。

    这种需要是通过简单但是非常有用的 tstamp 任务来解决的。这个任务通常在某次生成过程开始时调用,比如在一个 init 目标中。这个任务不需要属性,许多情况下只需 <tstamp></tstamp>就足够了。

    tstamp 不产生任何输出;相反,它根据当前系统时间和日期设置 Ant 属性。下面是 tstamp 设置的一些属性、对每个属性的说明,以及这些属性可被设置到的值的例子:

 属性  说明  例子
 DSTAMP  设置为当前日期,默认格式为yyyymmdd  20031217
 TSTAMP  设置为当前时间,默认格式为 hhmm  1603
 TODAY  设置为当前日期,带完整的月份  2003年12月17日

     例如,在调用 tstamp 任务之后,我们能够根据日期命名该 JAR 文件,如下所示:

 <jar basedir="classes" destfile="package-${DSTAMP}.jar"></jar>
因此,如果这个任务在 2003 年 12 月 17 日调用,该 JAR 文件将被命名为 package-20031217.jar。

    还可以配置 tstamp 任务来设置不同的属性,应用一个当前时间之前或之后的时间偏移,或以不同的方式格式化该字符串。所有这些都是使用一个嵌套的 format 元素来完成的,如下所示:

 <tstamp></tstamp>
   <format property="OFFSET_TIME"> </format>            pattern="HH:mm:ss"
           offset="10" unit="minute"/>

    上面的清单将 OFFSET_TIME 属性设置为距离当前时间 10 分钟之后的小时数、分钟数和秒数。

    用于定义格式字符串的字符与 java.text.SimpleDateFormat 类所定义的那些格式字符相同。

•创建和删除目录任务编写:

     —创建目录:

 <mkdir></mkdir>

    首先要注意 / 被用作目录分隔符,这是 UNIX 和 Linux 的惯例。您可能认为这不是很平台无关的,但是 Ant 知道如何处理它,并针对它运行所在的平台做恰当的事情,这与我们在前面定义基于位置的属性时所看到的方式相同。我们能够同样容易地使用 \,而不管平台是什么 ―― Ant 能够处理任一种形式,甚至能够处理两种形式的混合。

    mkdir 任务的另一个有用特性是它的如下能力:在父目录还不存在时创建它们。如果目标目录已经存在,mkdir 任务不会发出错误消息,而只是假设它的工作已经完成,从而什么也不做。

    —删除目录同样也很容易:

 <delete></delete>

    这将删除指定的目录连同它包含的所有文件以及子目录。使用 file 属性而不是 dir 属性可以指定要删除的单个文件。

    —复制和移动文件及目录:

 <copy file="src/Test.java" tofile="src/TestCopy.java"></copy>

    —使用 move 来执行重命名操作而不是拷贝文件:

 <move file="src/Test.java" tofile="src/TestCopy.java"></move>

   —将文件复制或移动到另一个目录:

 <copy file="src/Test.java" todir="archive"></copy>
<move file="src/Test.java" todir="archive"></move>

    默认情况下,Ant 仅输出它执行的移动和复制操作的摘要,包括诸如已移动或复制的文件的数量等信息。如果想看到更详细的信息,包括涉及的文件名称等,您可以将 verbose 属性设置为true。

•创建和解压缩 zip 及 tar 文件:

 <zip basedir="output" destfile="output.zip"></zip>

    相同的语法也可用于创建 tar 文件。 还可以使用 GZip 和 BZip 任务来压缩文件。例如:

 <gzip src="/developerWorks/cn/education/java/j-apant/tutorial/output.tar" zipfile="output.tar.gz"></gzip>

    解压缩和提取文件同样也很简单:

 <unzip src="/developerWorks/cn/education/java/j-apant/tutorial/output.tar.gz" dest="extractDir"></unzip>

    还可以包括 overwrite 属性来控制覆盖行为。默认设置是覆盖与正在被提取的归档文件中的条目相匹配的所有现有文件。相关的任务名称是 untar、unjar、gunzip 和 bunzip2。

•替换文件中的标记:

    replace 任务,它执行文件中的查找和替换操作。token 属性指定要查找的字符串,value 属性指定一个新的字符串,查找到的标记字符串的所有实例都被替换为这个新的字符串。例如:

 <replace value="new" file="input.txt" token="old"></replace>

    替换操作将在文件本身之内的适当位置进行。为了提供更详细的输出,可把 summary 属性设置为 true。这将导致该任务输出找到和替换的标记字符串实例的数目。

•模式匹配:

    一次对一组文件执行那些操作经常是有用的 ―― 例如对给定目录中以 .java 结尾的所有文件执行操作。

    这是使用通配符字符来完成的:*,它匹配零个或多个字符;以及 ?,它仅匹配一个字符。因而匹配以 .java 结尾的所有文件的模式不过就是 *.java。

    也可以对目录执行模式匹配。例如,模式 src*/*.java 将匹配带 src 前缀的任何目录中的所有 Java 文件。 还有另一种模式结构:**,它匹配任意数量的目录。例如,模式 **/*.java 将匹配当前目录结构下的所有 Java 文件。

    您能够以相当一致的方式对文件系统任务使用模式,比如嵌套的 fileset 元素。先前,我们使用这个任务来复制单个文件:

 <copy file="src/Test.java" todir="archive"></copy>

    如果我们想要使用一个模式,可以将 file 属性替换为一个 fileset 元素,如下所示:

 <copy todir="archive"></copy>
  <fileset></fileset>
    <include name="*.java"></include>
 

     fileset 默认情况下包含指定 src 目录下的所有文件,因此为了仅选择 Java 文件,我们对模式使用一个 include 元素。类似地,我们可以对另一个模式添加一个 exclude 元素,从而潜在地排除include指定的匹配项。甚至可以指定多个include 和 exclude 元素;这样将得到一组文件和目录,它们包含 include 模式的所有匹配项的并集,但排除了 exclude 模式的所有匹配项。

    注意还有一个通常很有用的文件集特性,但是对于没有意识到它的人来说,这个特性偶尔会产生混淆。这个特性称为 默认排除:即自动从文件集内容中排除的内置模式列表。该列表包括与名为 CVS 的目录相匹配的条目,以及以 ~ 字符结尾的文件,它们可能是备份文件。您通常不想在文件系统操作中包括这类文件和目录,因此排除这些文件是默认行为。然而,如果确实想无例外地选择 所有 文件和目录,可以将文件集的 defaultexcludes 属性设置为 no。
•使用选择器:

     正如我们已经看到的,文件集用于指定一组文件,并且这个组的内容可以使用 include 和 exclude 模式来指定。也可以结合称为 选择器 的特殊元素使用include 和 exclude 来选择文件。下面是对 Ant 可用的核心选择器的列表:

     —size:这个选择器用于根据文件的字节大小选择文件(除非使用 units 属性来指定了不同的单位)。when 属性用于设置比较的性质(less、more 或者 equal),value 属性定义每个文件将与之作比较的目标大小。

    —contains:只有包含给定文本字符串(由text 属性指定)的文件才匹配这个选择器。默认情况下,查找操作是大小写敏感的;添加casesensitive="no" 可以改变默认设置。

    —filename:name 属性指定文件名要与之匹配的模式。它本质上与 include 元素相同,以及与指定了negate="yes" 时的 exclude 元素相同。


    —present:从当前目录结构中选择如下文件:它们与指定的 targetdir 目录中的文件具有相同的名称和相对目录结构。


    —depend:这个选择器与 present 选择器具有相同的效果,只不过匹配的文件被限制到相对于 targetdir 位置中的对应文件来说,最近已修改过的那些文件。


    —date:这个选择器基于其最后修改日期选择文件。when 属性指定作比较的性质是 before、after 还是 equal,datetime 属性指定与之作比较的日期和时间,这个日期和时间具有给定的固定格式 MM/DD/YYYY HH:MM AM_or_PM。注意 Windows 平台上有一个内置的 2 秒偏移,以允许底层文件系统的不精确性 ―― 这可能导致匹配的文件数量超过预期。允许的回旋时间量可以使用 granularity 属性来更改(以毫秒为单位来指定)。


    —depth:这个选择器检查每个文件的目录结构层次数目。min 和/或 max 属性用于选择具有想要的目录层次数目的的文件。
还可以通过在一个选择器 容器 内嵌套一个或多个选择器来组合选择器。 最常用的选择器容器 and 仅选择它包含的所有选择器都选择了的文件。其他选择其容器包括 or、not、none 和 majority。

    下面是一个文件集的例子,它仅选择那些大于 512 字节并且包含字符串“hello”的文件。

 <fileset></fileset>
    <and></and>
        <contains text="hello"></contains>
        <size value="512" when="more"></size>
   


•将生成文件链接起来:

    有两种生成大型项目的不同方法。一种是让一个单一的生成文件做所有事情;另一种是让高级别的生成文件调用其它生成文件以执行特定任务,从而将生成过程划分为许多较小的部分。

    使用 ant 任务来从一个 Ant 生成中调用另一个 Ant 生成是很容易的。在简单的情况下,您可以使用 antfile 属性,仅指定那些要使用的生成文件,Ant 将生成该生成文件中的默认目标。例如:

 <ant antfile="sub-build.xml"></ant>

    在父生成文件中定义的任何属性默认将传递给子生成文件,虽然这可以通过指定 inheritAll="false"来避免。通过使用 property 元素来传入显式的属性也是可以做到的 ―― 即使将 inheritAll 设置为 false,这些属性也仍然适用于子生成文件。这个功能很适合用于给子生成文件传入参数。

    让我们来考虑一个例子。下面是我们想要调用的一个生成文件:

 <!---->
<project default="showMessage"></project>
    <target name="showMessage"></target>
        <echo message="Message=${message}"></echo>
   

   (我们在前面还没有遇到过 echo 任务 ―― 它简单地输出给定的消息。)

   下面是调用第一个生成文件的第二生成文件,它还给第一个生成文件传入 message 属性:

 <!---->
<project default="callSub"></project>
    <target name="callSub"></target>
        <ant antfile="sub.xml" target="showMessage" inheritall="false"></ant>
            <property name="message" value="Hello from parent build"></property>
       
   

    运行第二个生成文件所得到的输出如下:

 Buildfile: build.xml
callSub:
showMessage:
     [echo] Message=Hello from parent build
BUILD SUCCESSFUL
Total time: 0 seconds

•使用 CVS 知识库:

    CVS 是 concurrent versions system(并发版本控制系统) 的缩写。它是一个源代码控制系统,设计用于跟踪许多不同开发人员做出的更改。它非常流行,在开放源代码项目中特别受欢迎。Ant 提供了与 CVS 的紧密集成。这对于自动化生成环境是非常有用的,因为单个生成文件也可以从源代码知识库中提取出一个或多个模块,生成项目,甚至基于自从前次执行生成以来所作的变更生成批处理文件。

    注意,为了利用 Ant 中的 cvs 任务,您需要在机器上安装 cvs 命令,并使其从命令行可用。这个命令包括在大多数 Linux 发行套件中;它也以多种形式对 Windows 可用 ―― 例如作为宝贵的 Cygwin 环境的一部分。(请参阅参考资料以了解关于 Cygwin 的更多信息。)

   下面是从 CVS 知识库提取模块的一个例子生成文件:

 <!---->
<project name="CVS Extract" default="extract" basedir="."></project>
<property name="cvsRoot" value=":pserver:anonymous@dev.eclipse.org:/home/eclipse"></property>
    <target name="extract"></target>
        <cvs cvsroot="${cvsRoot}"></cvs>             package="org.eclipse.swt.examples"
                dest="${basedir}"/>
   

    cvs 任务的主要属性是 cvsRoot,它是对 CVS 知识库的完整引用,包括连接方法和用户详细信息。这个参数的格式如下:

 [:method:][[user][:password]@]hostname[:[port]]/path/to/repository

    在上面的例子中,我们作为匿名用户连接到 Eclipse 项目的中央知识库。然后其他属性指定了我们希望提取的模块以及放置提取文件的目的地。提取是 CVS 任务的默认操作;其他操作可通过使用 command 属性来指定。

    请参阅参考资料以了解关于 CVS 的更多信息。

•创建自定义的任务:

    为实现一个简单的自定义任务,我们所需做的就是扩展 org.apache.tools.ant.Task 类,并重写 execute() 方法。因此,作为这个文件排序自定义任务的框架,我们将编写如下代码:

 import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Task;
public class FileSorter extends Task {
       // The method executing the task
       public void execute() throws BuildException {}
}

    注意我们声明 execute() 方法抛出一个 BuildException 异常。如果这个任务出了任何错误,我们将抛出这个异常以便向 Ant 指出故障。

    大多数任务,不管是核心任务还是自定义任务,都利用属性来控制它们的行为。对于这个简单任务,我们需要一个属性来指定要排序的文件,需要另一个属性来指定排序内容的输出。我们把这两个属性分别叫做 file 和 tofile。

    Ant 使得支持自定义任务中的属性非常容易。为此,我们只需实现一个具有特别格式化的名称的方法,Ant 能够使用生成文件中指定的对应属性的值来调用这个方法。这个方法的名称需要是 set 加上属性的名称,因此在这个例子中,我们需要名为 setFile() 和 setTofile() 的方法。当 Ant 遇到生成文件中的一个属性设置时,它会寻找相关任务中具有适当名称的方法(称为 setter 方法)。

    生成文件中的属性是作为字符串来指定的,因此我们的 setter 方法的参数可以是一个字符串。在这样的情况下,Ant 将在展开值所引用的任何属性之后,使用该属性的字符串值来调用我们的方法。但有时我们想把属性的值看作是一种不同的类型。这里的示例任务就是这种情况,其中的属性值引用文件系统上的文件,而不只是引用任意的字符串。可以通过将方法参数声明为 java.io.File 类型来容易地做到这点。Ant 将接受属性的字符串值,并把它解释为一个文件,然后传递给我们的方法。如果文件是使用相对路径名称来指定的,则会被转换为相对于项目基目录的绝对路径。Ant 能够对其他类型执行类似的转换,比如 boolean 和 int 类型。如果您提供具有相同名称但是具有不同参数的两个方法,Ant 将使用更明确的那一个方法,因此文件类型将优先于字符串类型。

    这个自定义任务需要的两个 setter 方法类似如下:

     // The setter for the "file" attribute
    public void setFile(File file) {}
    // The setter for the "tofile" attribute
    public void setTofile(File tofile) {}

    现在我们能够完成这个简单的文件排序任务的实现:

  import java.io.*;
import java.util.*;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Task;
/**
 * A simple example task to sort a file
 */
public class FileSorter extends Task {
    private File file, tofile;
   
    // The method executing the task
    public void execute() throws BuildException {
        System.out.println("Sorting file="+file);
        try {
            BufferedReader from =
                new BufferedReader(new FileReader(file));
            BufferedWriter to =
                new BufferedWriter(new FileWriter(tofile));
            List allLines = new ArrayList();
            // read in the input file
            String line = from.readLine();
            while (line != null) {
                allLines.add(line);
                line = from.readLine();
            }
            from.close();
            // sort the list
            Collections.sort(allLines);
            // write out the sorted list
            for (ListIterator i=allLines.listIterator(); i.hasNext(); ) {
                String s = (String)i.next();
                to.write(s); to.newLine();
            }
            to.close();
        } catch (FileNotFoundException e) {
            throw new BuildException(e);
        } catch (IOException e) {
            throw new BuildException(e);
        }
    }
    // The setter for the "file" attribute
    public void setFile(File file) {
        this.file = file;
    }
    // The setter for the "tofile" attribute
    public void setTofile(File tofile) {
        this.tofile = tofile;
    }
}

    两个 setter 方法简单地对属性的值排序,以便这些值能够在 execute() 方法中使用。这里,输入文件被逐行地读入一个列表中,然后被排序并逐行地输出到输出文件。注意,为简单起见,我们很少执行错误检查 ―― 例如,我们甚至没有检查生成文件是否设置了必需的属性。不过我们的确至少捕捉了所执行的操作抛出的 I/O 异常,并将这些异常作为 BuildExceptions 重新抛出。

    现在可以使用 javac 编译器或从某个 IDE 内编译这个自定义的任务。为了解决所使用的 Ant 类的引用问题,您需要把 ant.jar 文件的位置添加到 classpath 中。这个文件应该在 Ant 安装路径下的 lib 目录。

    现在我们已经开发和编译了这个自定义的任务,下面可以从生成文件中利用它了。

    在能够调用自定义的任务之前,我们需要给它指定一个名称来 定义 它,并告诉 Ant 关于实现这个任务的类文件的信息,以及定位该类文件所必需的任何 classpath 设置。这是使用 taskdef 任务来完成的,如下所示:

 <taskdef name="filesorter"></taskdef>     classname="FileSorter"
    classpath="."/>

    现在可以像使用 Ant 的核心任务一样使用这个自定义的任务了。下面是一个完整的生成文件,它显示了这个自定义任务的定义和用法:

 <!---->
<project name="CustomTaskExample" default="main" basedir="."></project>
    <taskdef name="filesorter"></taskdef>        classname="FileSorter
       classpath="."/>
    <target name="main"></target>
        <filesorter file="input.txt" tofile="output.txt"></filesorter>
   

    现在在当前工作目录中创建一个 input.txt 文件来测试这个自定义的任务。例如:

Hello there
This is a line
And here is another one

    下面是运行上面的生成文件之后产生的控制台输出:

 Buildfile: build.xml
main:
[filesorter] Sorting file=E:\tutorial\custom\input.txt
BUILD SUCCESSFUL
Total time: 0 seconds

    注意 input.txt 的相对路径名称被转换成了当前目录中的一个绝对路径名称。这是因为我们将 setter 方法的参数指定为 java.io.File 类型而不是 java.lang.String 类型。

    现在看一下这个任务实际是否能工作。这时应该已经在同一目录中创建了名为 output.txt 的文件,它包含以下内容:

And here is another one
Hello there
This is a line

     你可以尝试指定一个不存在的输入文件,以确定该任务是如何向 Ant 报告 “file not found”异常的。

分享到:
评论
3 楼 wv1124 2009-11-11  
<!-- 得到当前日期 -->
<tstamp>
<format property="now.date" pattern="yyyy-MM-dd" locale="zh" />
</tstamp>

<!-- 创建临时目录 -->
<target name="createTemp" description="创建临时目录">
<mkdir dir="${temp}/${now.date}"/>
<echo>创建临时目录${temp}/{tstamp}</echo>
</target>
原来这样用,呵呵!
2 楼 wv1124 2009-11-11  
我这样用<mkdir dir="${temp}/${DSTAMP}"/>,
怎么创建WebRoot\tmp\${DSTAMP}这样的目录,没有换成日期,why?
1 楼 wv1124 2009-11-11  
DSTAMP好像不行吗?

相关推荐

    [附源码+数据库+毕业论文+部署教程+配套软件]基于SpringBoot+MyBatis+MySQL+Maven+Vue的停车场管理系统,推荐!

    一、项目简介 包含:项目源码、数据库脚本等,该项目附带全部源码可作为毕设使用。 项目都经过严格调试,eclipse或者idea 确保可以运行! 该系统功能完善、界面美观、操作简单、功能齐全、管理便捷 二、技术实现 jdk版本:1.8 及以上 ide工具:IDEA或者eclipse 数据库: mysql5.5及以上 后端:spring+springboot+mybatis+maven+mysql 前端: vue , css,js , elementui 三、系统功能 1、系统角色主要包括:管理员、用户 2、系统功能 前台功能包括: 用户登录 车位展示 系统推荐车位 立即预约 公告展示 个人中心 车位预定 违规 余额充值 后台功能: 首页,个人中心,修改密码,个人信息 用户管理 管理员管理 车辆管理 车位管理 车位预定管理,统计报表 公告管理 违规管理 公告类型管理 车位类型管理 车辆类型管理 违规类型管理 轮播图管理 详见 https://flypeppa.blog.csdn.net/article/details/146122666

    springboot656基于java-springboot的农机电招平台毕业设计(代码+数据库+论文+PPT+演示录像+运行教学+软件下载).zip

    项目已获导师指导并通过的高分毕业设计项目,可作为课程设计和期末大作业,下载即用无需修改,项目完整确保可以运行。 包含:项目源码、数据库脚本、软件工具等,该项目可以作为毕设、课程设计使用,前后端代码都在里面。 该系统功能完善、界面美观、操作简单、功能齐全、管理便捷,具有很高的实际应用价值。 项目都经过严格调试,确保可以运行!可以放心下载 技术组成 语言:java 开发环境:idea 数据库:MySql 部署环境:maven 数据库工具:navica 更多毕业设计https://cv2022.blog.csdn.net/article/details/124463185

    Python程序设计学习思维导图-仅供参考

    内容为Python程序设计的思维导图,适用于新手小白进行浏览,理清思路

    2024-Stable Diffusion全套资料(软件+关键词+模型).rar

    2024-Stable Diffusion全套资料(软件+关键词+模型).rar

    mmexport1741417035005.png

    mmexport1741417035005.png

    COMSOL三维锂离子电池全耦合电化学热应力模型:模拟充放电过程中的多物理场耦合效应及电芯内应力应变情况,COMSOL锂离子电池热应力全耦合模型,comsol三维锂离子电池电化学热应力全耦合模型锂离子

    COMSOL三维锂离子电池全耦合电化学热应力模型:模拟充放电过程中的多物理场耦合效应及电芯内应力应变情况,COMSOL锂离子电池热应力全耦合模型,comsol三维锂离子电池电化学热应力全耦合模型锂离子电池耦合COMSOL固体力学模块和固体传热模块,模型仿真模拟电池在充放电过程中由于锂插层,热膨胀以及外部约束所导致的电极的应力应变情况结果有电芯中集流体,电极,隔膜的应力应变以及压力情况等,电化学-力单向耦合和双向耦合 ,关键词: 1. COMSOL三维锂离子电池模型; 2. 电化学热应力全耦合模型; 3. 锂离子电池; 4. 固体力学模块; 5. 固体传热模块; 6. 应力应变情况; 7. 电芯中集流体; 8. 电极; 9. 隔膜; 10. 电化学-力单向/双向耦合。,COMSOL锂离子电池全耦合热应力仿真模型

    基于传递矩阵法的一维层状声子晶体振动传输特性及其优化设计与应用,声子晶体传递矩阵法解析及应用,Matlab 一维层状声子晶体振动传输特性 传递矩阵法在声子晶体的设计和应用中具有重要作用 通过调整声子

    基于传递矩阵法的一维层状声子晶体振动传输特性及其优化设计与应用,声子晶体传递矩阵法解析及应用,Matlab 一维层状声子晶体振动传输特性 传递矩阵法在声子晶体的设计和应用中具有重要作用。 通过调整声子晶体的材料、周期和晶格常数等参数,可以设计出具有特定带隙结构的声子晶体,用于滤波、减震、降噪等应用。 例如,通过调整声子晶体的周期数和晶格常数,可以改变带隙的位置和宽度,从而实现特定的频率范围内的噪声控制。 此外,传递矩阵法还可以用于分析和优化声子晶体的透射谱,为声学器件的设计提供理论依据。 ,Matlab; 一维层状声子晶体; 振动传输特性; 传递矩阵法; 材料调整; 周期和晶格常数; 带隙结构; 滤波; 减震; 降噪; 透射谱分析; 声学器件设计,Matlab模拟声子晶体振动传输特性及优化设计研究

    头部姿态估计(HeadPose Estimation)-Android源码

    头部姿态估计(HeadPose Estimation)-Android源码

    永磁同步电机FOC、MPC与高频注入Simulink模型及基于MBD的代码生成工具,适用于Ti f28335与dspace/ccs平台开发,含电机控制开发文档,永磁同步电机控制技术:FOC、MPC与高

    永磁同步电机FOC、MPC与高频注入Simulink模型及基于MBD的代码生成工具,适用于Ti f28335与dspace/ccs平台开发,含电机控制开发文档,永磁同步电机控制技术:FOC、MPC与高频注入Simulink模型开发及应用指南,提供永磁同步电机FOC,MPC,高频注入simulink模型。 提供基于模型开发(MBD)代码生成模型,可结合Ti f28335进行电机模型快速开发,可适用dspace平台或者ccs平台。 提供电机控制开发编码器,转子位置定向,pid调试相关文档。 ,永磁同步电机; FOC控制; MPC控制; 高频注入; Simulink模型; 模型开发(MBD); Ti f28335; 电机模型开发; dspace平台; ccs平台; 编码器; 转子位置定向; pid调试。,永磁同步电机MPC-FOC控制与代码生成模型

    light of warehouse.zip

    light of warehouse.zip

    考虑温度和气体排放等因素的工业乙醇发酵过程及其Matlab源码-乙醇发酵-气体排放-Matlab建模和仿真-代谢路径

    内容概要:文章深入讨论了工业乙醇发酵的基本原理及工艺流程,特别是在温度和气体排放(如CO2及其他有害气体)影响下的发酵效果分析。文章介绍了乙醇发酵的重要环节,如糖分解、代谢路径、代谢调控以及各阶段的操作流程,重点展示了如何通过Matlab建模和仿真实验来探索这两个关键环境因素对发酵过程的具体影响。通过动态模型仿真分析,得出合适的温度范围以及适时排除CO2能显著提升发酵产乙醇的效果与效率,从而提出了基于仿真的优化发酵生产工艺的新方法。 适用人群:从事生物工程相关领域研究的科学家、工程师及相关专业师生。 使用场景及目标:适用于实验室环境、学术交流会议及实际生产指导中,以提升研究人员对该领域内复杂现象的理解能力和技术水平为目标。 其他说明:附录中有详细的数学公式表达和程序代码可供下载执行,便于有兴趣的研究团队重复实验或者继续扩展研究工作。

    Tomcat资源包《Tomcat启动报错:CATALINA-HOME环境变量未正确配置的完整解决方案》

    本资源包专为解决 Tomcat 启动时提示「CATALINA_HOME 环境变量未正确配置」问题而整理,包含以下内容: 1. **Apache Tomcat 9.0.69 官方安装包**:已验证兼容性,解压即用。 2. **环境变量配置指南**: - Windows 系统下 `CATALINA_HOME` 和 `JAVA_HOME` 的详细配置步骤。 - 常见错误排查方法(如路径含空格、未生效问题)。 3. **辅助工具脚本**:一键检测环境变量是否生效的批处理文件。 4. **解决方案文档**:图文并茂的 PDF 文档,涵盖从报错分析到成功启动的全流程。 适用场景: - Tomcat 9.x 版本环境配置 - Java Web 开发环境搭建 - 运维部署调试 注意事项: - 资源包路径需为纯英文,避免特殊字符。 - 建议使用 JDK 8 或更高版本。

    java毕业设计源码 仿360buy京东商城源码 京东JavaWeb项目源代码

    这是一款仿照京东商城的Java Web项目源码,完美复现了360buy的用户界面和购物流程,非常适合Java初学者和开发者进行学习与实践。通过这份源码,你将深入了解电商平台的架构设计和实现方法。欢迎大家下载体验,提升自己的编程能力!

    java-springboot+vue的乒乓球馆预约管理系统源码.zip

    系统选用B/S模式,后端应用springboot框架,前端应用vue框架, MySQL为后台数据库。 本系统基于java设计的各项功能,数据库服务器端采用了Mysql作为后台数据库,使Web与数据库紧密联系起来。 在设计过程中,充分保证了系统代码的良好可读性、实用性、易扩展性、通用性、便于后期维护、操作方便以及页面简洁等特点。

    【javaweb毕业设计源码】大学生求职就业网

    这是一款专为大学生打造的求职就业网JavaWeb毕业设计源码,功能齐全,界面友好。它提供简历投递、职位搜索、在线交流等多种实用功能,能够帮助你顺利进入职场。无论你是想提升技术水平还是寻找灵感,这个源码都是不可多得的资源。快来下载,让你的求职之路更加顺畅吧!

    useTable(1).ts

    useTable(1).ts

    DSP实验报告汇总.pdf

    实验一: 1、进行CCS6.1软件的安装,仿真器的设置,程序的编译和调试; 2、熟悉CCS软件中的C语言编程; 3、使用按键控制LED跑马灯的开始与停止、闪烁频率; 4、调试Convolution、FFT、FIR、FFT-FIR实验,编制IIR算法并调试,并在CCS软件上给出实验结果。 实验二: 1、利用定时器周期中断或下溢中断和比较器比较值的修改来实现占空比可调的PWM波形; 2、改变PWM占空比控制LED灯的亮暗,按键实现10级LED灯亮暗调整; 3、模拟数字转换,转换过程中LED指示,并在变量窗口显示转换结果; 4、数字模拟转换,产生一个正弦波,转换过程中LED指示,转换完成后在CCS调试窗口显示波形。 实验三: 1、SCI异步串行通信实验; 2、SPI及IIC同步串行通信实验; 3、CAN现场总线串行通信实验; 4、传输过程中LED指示。 实验四: 1、电机转速控制实验。

    LINUX系统管理与配置.docx

    LINUX系统管理与配置.docx

    chromedriver-mac-x64-136.0.7055.0.zip

    chromedriver-mac-x64-136.0.7055.0.zip

    中国标准地图-审图号GS(2020)4619号-shp格式

    地级城市驻地,dbf 地级城市驻地,prj 地级城市驻地.sbn 9 地级城市驻地.sbx 地级城市驻地.shp 地级城市驻地.shx 9 国界线.dbf 国界线.prj 国界线.sbne 国界线.sbx 国界线.shp 国界线.shx )经纬网.dbf ]经纬网.prj 经纬网.sbn 经纬网.sbx 经纬网.shp 经纬网.shx 全国县级统计数据.dbf 全国县级统计数据,prj 全国县级统计数据.sbr 全国县级统计数据.sbx 全国县级统计数据.shp 全国县级统计数据.shx )省会城市.dbf 省会城市,prj 省会城市.sbn 省会城市.sbx 省会城市.shp 省会城市.shx 省级行政区.dbf 省级行政区,pn 省级行政区.sbn 省级行政区,sbx 9 省级行政区.shp 9 6 省级行政区,shx 县城驻地.dbf 县城驻地,prj 擷垃岑械鰣媛城驻地.sbr 藶勇瑁鴎隐城驻地.sbx 县蓿玨蒴城驻地.shp 苽6城驻地,shx 线状省界.dbf 线状省界,prj 1线状首界,sbn 线状省界.sbx 线状首界.shp 线状省界,shx 线状县界,dbf □]

Global site tag (gtag.js) - Google Analytics