`
bluestar
  • 浏览: 375824 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

(转)Ant: 大规模应用中的应用

    博客分类:
  • java
阅读更多

Large Scale 的应用通常意味着:

  1. 目录较多, 层次较深

  2. 依赖较多, 构建脚本依赖的第三方Ant Task, 项目依赖的第三方库等

  3. 测试较多, 构建时间反馈周期较长

  4. 需要在不同操作系统上运行

  5. 需要在不同团队成员的机器上运行

  6. 由于以上原因, 导致Ant脚本较长

1. 目录较多, 层次较深

通常有两种风格的解决方案

  1. 一是使用Ant-Contrib中的<foreach> 来遍历子目录并依次调用其中的构建脚本, 一般是缺省的target

  2. 另外一种是用Ant自身的<subant> 命令来搜索构建脚本并调用特定的target

第一种方案可看作深度优先, 不同的子目录通常是系统的不同组件, 这种方式是把单个组件全部构建完再构建另外的组件

第二种方案可看作广度优先, 类似于模板方法, 要求每个子系统的构建脚本都要定义特定的约定的target, Root构建脚本会先调用所有构建脚本的某个target, 再调用另外的target

当然也可以用<foreach> 来实现第二种风格

2. 依赖较多, 构建脚本依赖的第三方Ant Task, 项目依赖的第三方库等

  1. 明确区分构建脚本的依赖和你的项目的依赖. 那些第三方的Ant Task通常你只会在构建过程中用到它们, 而不会在产品中用到, 如 Checkstyle, Emma 等, 把它们放在单独的目录中, 打包时不要理会它们. 关于区分不同依赖的经验, 参考<<CruiseControl Enterprise 最佳实践 (2) : Keep your dependencies to yourself >>

  2. 使用 ivy 来管理你项目的依赖

  3. 清理不必要的依赖或干扰:

  1. 总是提供 <clean> target, 并借助工具保证在需要的时刻总是能够得到执行, 参见后面的章节

  2. 定义单独的目录来存放项目所有的输出, 通常是顶级目录下的名字叫做 target或者build或者dist之类的目录, 其内部的层次结构应该与源文件的目录结构一致

  3. 构建过程中拷贝需要的资源到上面定义的输出目录中, 而不是直接对资源操作

3. 测试较多, 构建反馈周期较长

一般你不会希望直到构建过程的末尾某个任务才失败, 这样你修正后不得不从头再跑一遍来校验, 有几种方式来来缩短反馈时间

  1. 一种是先运行最可能失败的任务, 利用前面提到的<subant><foreach>

  2. 一种是为每个任务都定义单独的target, 或用"property"来选择或忽略特定的target. 参见 target 的 if/unless 属性, 及 Condition 元素. 如用property来控制运行所有测试还是某个测试:

    <junit ...>

      <!-- ... -->

      <test name="${testcase}" if="testcase" />

      <batchtest todir="${test.data.dir}" unless="testcase" >

          <fileset dir="${test.classes.dir}" includes="**/*Test.class" />

      </batchtest>

    </junit>

另外你希望一次构建能够发现尽可能多的问题, 而不是出现第一个问题后构建就停止, 这样的话可以批量修复它们然后再重新运行一次构建, 而不是一遍一遍的运行构建来逐个找出错误

  1. 可以用一些任务提供的 haltonerror, haltonfailure, errorproperty 等来控制构建结束的时机和最后的结果, 如:

    <junit haltonerror="false" haltonfailure="false" errorProperty="test.failed" failureProperty="test.failed"

 ...>
        <!-- ... -->
    </junit>
    <fail if="test.failed"

>Tests failed.  Check log or reports for details</fail> 

4. 需要在不同操作系统上运行

  1. 利用 <exec > 的 os 或 osfamily 属性来控制不同操作系统上的行为

  2. 路径分隔符统一使用 "/"

5. 需要在不同团队成员的机器上运行, 每个人环境都不一样

其实这是配置管理的问题, 项目的所有文档和依赖, 甚至包括Ant本身都应该包含在一个单根目录下, 并且Check in到版本控制系统中. 里面所有涉及路径的地方都使用相对路径. 这样项目就可以即拷即用

但总有一些对外部环境的依赖, 这是就要借助 Ant 强大而合理的 immutable property 体系

  1. 所有可能变化的地方都使用 property 来引用

  2. 优先使用 JVM 的系统属性, 而不是环境变量

  3. 使用 user.properties 文件定义环境相关的property, 并在构建脚本中最先引入 < property file ="${ user.home} /user.properties" />

  4. 在引入 user.properties 之后, 为所有属性定义合理的缺省值, 以处理 user.properties 不存在不完整的情况

  5. 后面两步也可以用 <propertyfile> 来代替

一个应用就是可以在命令行传入用户名和密码而不是把它们写在脚本中, 这样就避免了安全和隐私问题

其它的例子包括用 property 来定义 test filter, 或者来定义碰到第一次错误是退出还是继续运行构建等

关于目录的处理

  1. 为根目录定义属性, 以此为起点定义子目录的属性

  2. 总是使用 ${basedir} 作为相对路径的前缀. 这样可以保证即使 Ant 的工作路径不同, 只要传递了正确的 basedir 属性, 所有的相对路径还是正确的.

  3. 使用 location 定义路径, 而不是 value. Ant会将 location 展开为绝对路径, 这样即使传递到另外的 Ant Project 中, 它的值也不会变

6. 由于以上原因, 导致Ant脚本较长

Ant不是Script Language, 你更应该像编写产品代码一样认真对待它的编写风格

  1. 前面说过通过命令行参数控制执行的target, 参数多了, 就要有 Usage, Help

    <target name="usage">
        <echo message="  Execute 'ant a' for a."/>
        <echo message="  Execute 'ant b' for b."/>
        <echo message="  Execute 'ant -Dtest.filter=**/*SeleniumTest.class' for specific test cases."/>
        <echo message="  Execute 'ant -Dsome.property=xxx' for xxx."/>
    </target> 
    <target name="help" depends="usage"/> 
  1. 模块化构建脚本, 使用 <macrodef>

  2. 抽取可复用的 macrodef 或 target 到单独的脚本中, 并在其它脚本中 import 这个可复用的文件, 这样有助于分离关注点, 使脚本更易维护

借助第三方工具来弥补Ant的局限

  1. 缺乏异常处理机制, 任何 BuildException 都会终止 Ant 的执行, 而任何 Task 都可能出现异常, 这样有些清理操作就得不到执行. 解决方案:

    a. Ant-Contrib的 <trycatch>

    b. CruiseControl 的 AntPublisher. CruiseControl定义了构建结束后的操作, 参见 <<CruiseControl Enterprise 最佳实践 (1) : Publish with a Publisher >>

  2. 缺乏依赖管理机制

    前面已经提到, 借助 ivy 来管理, ivy 已经成为了 Ant 的子项目

其它一些常用的风格

  1. Define tasks, datatypes, and properties before targets.

  2. Order attributes logically and consistently.

  3. Separate words in target names with a hyphen .

  4. Separate words with a dot (.) character in property names .

  5. Include an "all" target that builds it all.

  6. Define reusable paths.

  7. Use explicit classpaths wherever possible.

  8. Provide visual and XML test results. Use <formatter type="brief" usefile="false"/> , <formatter type="xml"/> and <junitreport>.

  9. 用以连字符(-)开头的target名字来定义无法从命令行调用的"内部"target

其它一些常用的技巧

  1. 与用户交互, 这在持续集成环境中应该不多: <input>

  2. 并发执行: <parallel> , 通常用来执行在后台运行的任务

  3. 递归的property定义. Ant 缺省并不支持 property 的递归展开, 如 ${${os}.${prop}}. 但任何事情都可以用一个额外的中间层解决, 这里可以借用的机制是 <macrodef>

Here is the macro (along lines suggested by Peter Reilly with reference to http://ant.apache.org/faq.html#propertyvalue-as-name-for-property :

<!-- Allows you define a new property with a value of ${${a}.${b}} which can't be done by the Property task alone.  -->
<macrodef name="dymanic-property">
    <attribute name="name"/>
    <attribute name="prop"/>
    <attribute name="os"/>
    <sequential>
        <property name="@{name}" value="${@{os}.@{prop}}"/>
    </sequential>

</macrodef>

这样就可以动态的定义属性

<macro.compose-property name="some.property" prop="${component} os="${targetOS}"/>

<do-something-with property="${some.property}"/>

诡异 的地方

  1. spawn, 不要使用spawn=true, 使用前面的<parallel>

    缺省spawn等于false, 这种情况下Ant退出时会把所有fork的进程都杀掉. 把spawn设置成true可以令进程寿命长于Ant, 从而可以不堵塞Ant的执行而用来运行后台程序. 但会带来很多不好的地方,比如不能即时在console看到信息等. 并且寿命长于 Ant 在某些情况下不是我们期待的, 比如在 CruiseControl 的环境中运行 Ant, 如果Ant fork的进程没有随着Ant退出而退出, 那么CruiseControl会认为Ant进程还没有结束, 从而一直在那里等待而不是执行后面的 Publishers.

    <parallel> 的<daemon>来运行后台程序

  2. unix上的通配符 (Windows上没问题): On Unix-like systems, wildcards are understood by shell intepreters, not by individual binary executables as /usr/bin/ls or shell scripts.

    <target name="list">
        <exec executable="sh">
        <arg value="-c"/>
        <arg value="ls /path/to/some/xml/files/*.xml"/>
        </exec>
    
        </target>
    
  3. 几个没在 jdk 文档中说明的系统属性
    ? -Duser.country=EN -Duser.language=US
    

参考

分享到:
评论

相关推荐

    YOLO-Ant:通过深度可分离卷积和大核设计实现天线干扰源检测的轻量级探测器

    ### YOLO-Ant:深度可分离卷积与大核设计下的天线干扰源检测轻量级探测器 #### 概述 随着5G通信时代的到来,如何有效地消除那些对通信造成干扰的因素变得尤为重要。目前,尽管计算机视觉技术正在迅速发展,并已经...

    Ant入门-ant入门pdf

    11. **Ant与持续集成**:简述Ant在持续集成工具(如Jenkins、Hudson)中的应用。 12. **实战案例**:提供实际项目构建的例子,帮助读者将理论知识应用于实践。 通过学习这本书,初学者将能够掌握Ant的基本操作,为...

    apache-ant-1.9.5

    - 性能优化:版本更新通常会带来性能提升,更快的构建速度对于持续集成和大规模项目尤其重要。 - 错误修复:1.9.5版本可能会修复前一版本中的一些已知问题,保证构建过程的稳定性和可靠性。 为了在Qt on Android...

    ant启动关闭tomcat

    Tomcat不仅简单易用,而且性能稳定,被广泛应用于各种规模的项目中。 ### 二、使用Ant启动Tomcat 为了通过Ant启动Tomcat,我们首先需要在Ant的构建脚本中定义一个目标(target),该目标将执行启动Tomcat的脚本。...

    ant java ant

    总的来说,Ant作为Java项目管理的重要工具,其强大的灵活性和可扩展性使其在各种规模的项目中都有广泛的应用。熟练掌握Ant的使用,不仅能提升开发效率,还能更好地理解和实践Java项目的构建流程。通过阅读相关书籍和...

    ant-designer-vue离线文档1.+版本

    4. **高性能**:通过精心优化,Ant Design Vue确保了在大规模应用中的流畅性能。 5. **完善的API和示例**:离线文档中详尽的API文档和示例代码,使得开发者能快速上手,减少学习曲线。 6. **国际化支持**:内置多...

    apache-ant-1.9.1

    2. **更好的性能**:通过优化内部实现,Ant在执行任务时的性能得到了提升,使得大规模项目的构建更加高效。 3. **增强的错误处理**:Ant 1.9.1提供更详细的错误报告和异常处理,有助于开发者更快地定位和解决问题。 ...

    ant概念

    **Ant**是一款开源的Java构建工具,主要用于自动化构建Java应用程序。它的设计理念旨在简化构建过程并提高跨平台能力。Ant由Apache软件基金会开发,作为Jakarta项目的一部分,现已独立成为一个重要的工具。 #### 二...

    apache-ant-1.9.4

    Apache Ant 是一个由Apache软件基金会开发的Java库和命令行工具,它的设计...无论是小型项目还是大型企业级应用,都能从Ant的特性中受益。通过合理的配置和使用,你可以大大提高开发效率,确保项目的构建过程顺利进行。

    React 和 Ant Design 在蚂蚁金服的实践(95页).pdf

    React 和 Ant Design 是蚂蚁金服的主要技术栈,用于构建大规模的应用程序。 架构解决方案:蚂蚁金服的技术架构是基于 React 和 Ant Design 的。React 负责构建用户界面,而 Ant Design 负责提供统一的设计语言和...

    ant应用开发

    ### Ant应用开发详解 #### 一、Ant简介与安装配置 Apache Ant 是一款开源的、跨平台的构建工具,主要用于Java项目的自动化构建和部署。它通过XML格式的配置文件(通常命名为`build.xml`)来定义项目的构建过程,极...

    Vue版AntDesignPro基于Elementui实现

    3. **状态管理**:由于项目规模较大,通常会采用Vuex进行全局状态管理,以解决组件间的数据通信问题。Vuex提供了一套集中式的状态管理模式,可以清晰地追踪应用的状态变化。 4. **路由管理**:Vue Router是Vue.js...

    Ant 文档

    《Ant 文档》 ...总之,Apache Ant是Java世界中不可或缺的构建工具,它的强大功能和灵活性使得它在各种规模的项目中都有所应用。通过理解和掌握Ant,开发者可以高效地管理项目构建流程,提高开发效率。

    使用ANT远程发布Web项目

    ### 使用ANT远程发布Web项目 #### 一、概述 在软件开发过程中,自动化构建与部署是提高开发效率...此外,对于大规模项目来说,使用Ant这样的工具还可以方便地集成到CI/CD流程中,进一步提升开发和运维的自动化水平。

    jmeter+ant自动话及优化报告

    - **分布式测试**:当需要更大规模的并发测试时,JMeter支持分布式模式,可以在多台机器上并行运行测试。 综上所述,这个主题涵盖了使用JMeter进行性能测试,通过Ant进行自动化调度,以及利用json-lib处理JSON数据...

    ant文档集合(自己学习ant时的资料)

    10. **Ant的进阶应用** - Ant与Ivy结合:Ivy是一个依赖管理工具,可以弥补Ant在处理外部库依赖上的不足。 - Ant与JUnit集成:进行自动化单元测试。 - Ant与Eclipse/IntelliJ IDEA集成:在IDE中直接运行Ant脚本,...

    Ant colony optimization

    这些算法的优势在于能够有效地处理大规模问题,并且通常能够获得较好的解。 #### 理论成果 近年来,关于蚁群优化的理论研究也取得了重要进展,例如对算法收敛性的分析、复杂度分析等。这些研究成果不仅有助于理解...

    DBMonster In Action 使用Ant自动产生数据库随机测试数据

    1. **DBMonster**:DBMonster是一个开源工具,专门设计用来生成大规模的数据库测试数据。它可以生成各种类型的数据,包括字符串、数字、日期等,并可以定制数据分布以模拟实际应用中的情况。使用DBMonster,开发者...

    ANT 超低功耗无线传感网络

    - **优势**: 大规模节点支持使得ANT能够构建覆盖范围广、节点数量众多的网络。 - **应用场景**: 城市级智能交通系统等。 **5. 信息类型** - **广播**: 单向发送数据给所有接收者。 - **确认**: 发送数据后需要...

Global site tag (gtag.js) - Google Analytics