我有一个非常基本的蚂蚁任务,它的行为很奇怪。
不超过build.xml,没有任何依赖项:
<project name="Test" default="recreate-via-http" >
<target name="recreate-via-http">
<loadresource property="result" >
<url url="http://someserver/somecall.php" />
</loadresource>
<echo>${result}</echo>
</target>
</project>
奇怪的是,这被执行了两次,而ant脚本中的其他内容只运行一次。
这意味着,http调用到达服务器两次。我甚至使用wireshark捕获了HTTP流量,它确认HTTP调用被执行了两次。
它们甚至似乎在同一时间被精确到毫秒。
在console输出中只显示一次。
ant脚本是通过eclipse内置ant启动的,但是当使用独立ant从windows命令行调用时,问题仍然存在。所以我不认为这是IDE或目标链的问题。
谢谢你的帮助!
编辑:为了它的价值,这里是一个链接到蚂蚁任务,我已经报告。https://issues.apache.org/bugzilla/show_bug.cgi?id=51762
您所看到的是来自Ant的未记录且有争议的错误行为。我还没有在bug数据库中查找,但如果您感兴趣,这里有链接:http://ant.apache.org/bugs.html
LoadResource任务首先检查资源的大小,然后将流读入缓冲区(在第126行查找execute方法)。URLResource类打开连接以读取Content-Length
标头,但随后关闭连接。这意味着它必须重新打开连接才能从中获取流。
我相信第282行的close()
调用可以而且应该被删除。然而,Ant开发人员把它放在那里可能是有原因的。我将让你来报告/投票这种行为。
----与完整的ant文件列表对齐,现在可以使用----
您的目标依赖关系可能会导致任务被调用两次。如果你想确保它只被调用一次,在它周围加上这样的东西:
<target name="recreate-via-http" unless="recreate-via-http.done">
<property name="recreate-via-http.done" value="true"/>
<loadresource property="result" >
<url url="http://someserver/somecall.php" />
</loadresource>
<echo>${result}</echo>
</target>
如果它在设置了这样的保护之后被调用了两次,那么它就是ant任务的loadresource实现中的代码,或者ant被一些外部项目(如IDE)调用了两次。无论哪种方式,它都不是依赖链中的错误。
解决这个问题的唯一方法是访问url,并检查文件是否需要下载;然后,如果确实需要下载,就下载。
<target name="recreate-via-http">
<antcall="check.recreate-via-http"/>
<antcall="execute.recreate-via-http"/>
</target>
<target name="check.recreate-via-http">
... access the remote URL, and
get it's last modified time
... access the local file copy, and
get it's last modified time
... call an ant condition to determine
if the two times are the same, setting
a property 'execute.recreate-via-http.notNeeded'
if they are identical.
</target>
<target name="execute.recreate-via-http" unless="execute.recreate-via-http.notNeeded">
<loadresource property="result" >
<url url="http://someserver/somecall.php" />
</loadresource>
<echo>${result}</echo>
</target>
在这种框架下,每次都会执行验证,但只有在修改时间不同时才会更新文件。一旦文件不是每次都更新,其他任务可能不会检测到它是新的,并且执行较少的工作(如果它们被编写为跳过已经完成的工作,如javac, copy, mkdir等)。
我的解决方法是:
<get src="http://yourURL" dest="/dev/null" />
或在Windows上:(在Windows 7上测试)
<get src="http://yourURL" dest="NUL" />
dest属性是必需的。我实际上并不想下载任何东西,所以我把它丢弃了。
我不知道这是否需要任何依赖,在我弄清楚之前我已经安装了所有的ant依赖。