如何让Ant在“等待”任务中加载和检查URL资源?

3
我正在编写一个Ant目标,用于运行测试,在测试开始之前需要运行一个应用服务器。我使用waitFor任务来ping URL,直到它得到响应。这很有效,但我不仅需要确保URL可以访问,还需要检查特定状态字符串是否存在。这第二个要求本身很简单,可以用gettelnet任务,然后进行子字符串搜索。但是'waitfor'任务除了标准Ant条件或可包装的东西(返回布尔值的东西)之外,不接受任何嵌套元素。我尝试在运行'waitfor'任务之前将URL加载为资源,并使用resourcecontains条件,但那会缓存响应,并且不会从服务器刷新。
有没有办法强制在每次循环中加载URL?还是其他实现方式?
以下是我想要实现的伪代码:
<waitfor>
    <and>
        <!-- make sure the URL is accessible at all -->
        <http url="theurl.jsp"/>

        <!-- load the URL as a resource and make sure it contains a substring -->
        <!-- moving the "url" task before the waitfor works if all conditions are met the first time through, but does not refresh the URL if it has to loop over again. having it inside like this, fails because waitfor/and don't support nexted "url" tasks -->
        <url id="url.resource" url="url.jsp"/>
        <resourcecontains refid="url.resource" substring="status"/>
    </and>
    <!-- else, keep on trying until timeout -->
</waitfor>
<!-- continue on to the tests to be run -->
2个回答

1

使用方法:

   <typedef
      name="httpcontains"
      classname="HttpContains"
   />

  <waitfor maxwait="10" maxwaitunit="minute" checkevery="500">
    <httpcontains contains="Running" url="http://myurl"/>
  </waitfor>

以下代码可以实现此功能:
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.ProjectComponent;
import org.apache.tools.ant.taskdefs.condition.Condition;

/**
 * Condition to wait for a HTTP request to succeed. Its attribute(s) are:
 *   url - the URL of the request.
 *   errorsBeginAt - number at which errors begin at; default=400.
 * @since Ant 1.5
 */
public class HttpContains extends ProjectComponent implements Condition {
    private String spec = null;
    private String contains = null;
    /**
     * Set the url attribute
     *
     * @param url the url of the request
     */
    public void setUrl(String url) {
        spec = url;
    }

    public void setContains(String s){
       contains = s;
    }

    private int errorsBeginAt = 400;

    /**
     * Set the errorsBeginAt attribute
     *
     * @param errorsBeginAt number at which errors begin at, default is
     *                      400
     */
    public void setErrorsBeginAt(int errorsBeginAt) {
        this.errorsBeginAt = errorsBeginAt;
    }

    /**
     * @return true if the HTTP request succeeds
     * @exception BuildException if an error occurs
     */
    public boolean eval() throws BuildException {
        if (spec == null) {
            throw new BuildException("No url specified in http condition");
        }
        log("Checking for " + spec, Project.MSG_VERBOSE);
        try {
            URL url = new URL(spec);
            try {
                URLConnection conn = url.openConnection();
                if (conn instanceof HttpURLConnection) {
                    HttpURLConnection http = (HttpURLConnection) conn;
                    int code = http.getResponseCode();
                    log("Result code for " + spec + " was " + code,
                        Project.MSG_VERBOSE);
                    if (code > 0 && code < errorsBeginAt) 
                    {
                       if ( evalContents(url) )
                          return true;
                       else
                          return false;

                    } else {
                        return false;
                    }
                }
            } catch (java.io.IOException e) {
                return false;
            }
        } catch (MalformedURLException e) {
            throw new BuildException("Badly formed URL: " + spec, e);
        }
        return true;
    }

    public boolean evalContents(URL mUrl )
    {
       try
       {

          String contents;

          StringBuffer buffer = new StringBuffer();
          byte[] buf = new byte[1024];
          int amount = 0;
          InputStream input = mUrl.openStream();

          while ((amount = input.read(buf)) > 0) 
          {   
             buffer.append(new String(buf, 0, amount));
          }
          input.close();
          contents = buffer.toString();

          log("Result code for " + contents,
                Project.MSG_VERBOSE);

          if ( contents.indexOf(contains) > -1 )
          {

             log("Result code for " + contents.indexOf(contains),
                   Project.MSG_VERBOSE);
             return true;

          }






          return false;
       }
       catch ( Exception e )
       {
          e.printStackTrace();
          log("Result code for " + e.toString(),
                Project.MSG_VERBOSE);

          return false;
       }
    }
}

我正在使用Ant 1.8.2并且出现错误:无法找到typedef类HttpContains 使用类加载器AntClassLoader[] - kamal

1

您可以通过在waitfor中的scriptcondition元素中调用目标来实现此目的。以下是一个示例。

要使用它,您需要将theurlcontent.matches属性分别设置为相关资源和要匹配的字符串。根据需要调整“maxwait”设置。

超时时设置theurl.fail属性。

<target name="lr">
    <local name="local.data" />
    <loadresource property="local.data">
        <url url="${theurl}" />
    </loadresource>
    <condition property="theurl.matches">
       <matches pattern="${content.matches}" string="${local.data}"/>
    </condition>
</target>

<waitfor maxwait="10" maxwaitunit="second" timeoutproperty="theurl.fail">
    <scriptcondition language="javascript" value="false">
    <![CDATA[
        project.getTargets().get( "lr" ).execute( );
        if ( project.getProperty( "theurl.matches" ) )
            self.setValue( true );
    ]]>
    </scriptcondition>
</waitfor>

这里利用了 Ant local 任务,该任务在 v1.8 中新增。 lr 目标获取 URL 并查找匹配项,如果匹配成功,则设置属性 theurl.matchesscriptconditionwaitfor 内执行目标,直到成功或超时。

我已经将其与美国海军天文台主钟时间和各种短时间字符串进行了测试,表现良好。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接