在Java中重试超时连接

时间:2011-09-05 21:13:33

标签: java

我有一个方法(下面),它下拉并以String形式返回网页的来源。一切正常,花花公子,但是当连接超时时,程序会抛出异常并退出。有没有更好的方法来执行此操作以允许它在超时时再次尝试,或者是否有办法在此方法中执行此操作?

public static String getPage(String theURL) {
    URL url = null;
    try {
        url = new URL(theURL);
    } catch (MalformedURLException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
        exitprint();
    }
    InputStream is = null;
    try {
        is = url.openStream();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
        exitprint();
    }
    int ptr = 0;
    StringBuffer buffer = new StringBuffer();
    try {
        while ((ptr = is.read()) != -1) {
            buffer.append((char)ptr);
        }
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
        exitprint();
    }

    return buffer.toString();
}

5 个答案:

答案 0 :(得分:8)

以下是您的代码的重构,应该重试下载N次。虽然没有测试过,但是它应该会朝着正确的方向开始。

public static String getPage(String theURL) {

    URL url = null;
    try {
        url = new URL(theURL);
    } catch (MalformedURLException e) {
        e.printStackTrace();
        exitprint();
    }

    for (int i = 0; i < N; i++) {

        try {
            InputStream is = url.openStream();

            int ptr = 0;
            StringBuffer buffer = new StringBuffer();

            while ((ptr = is.read()) != -1)
                buffer.append((char)ptr);

        } catch (IOException e) {
            continue;
        }

        return buffer.toString();
    }

    throw new SomeException("Failed to download after " + N + " attepmts");
}

答案 1 :(得分:1)

围绕它编写一个包装函数,并允许连接异常传播出去。然后,您可以循环调用现有函数,同时接收连接异常,直到某些最大重试次数。

这比在现有函数中嵌入for循环更好,因为它在逻辑上将重试逻辑与主线代码分开。结果更容易理解和理解。

答案 2 :(得分:1)

你可以将整个事情放在while循环中:

while (true) {

  try {
    ...
  } catch (IOException e) {
    continue;
  }

  return buffer.toString();
}

return语句会让你脱离循环。您可能还想跟踪尝试次数并在5-10之后停止,以获得礼貌,但这是它的基本形状。

修改

更好的版本,基于评论:

int retries = 10;
for (int i = 0 ; i < retries ; i++) {

  try {
    ...
  } catch (IOException e) {
    continue;
  }

  return buffer.toString();
}

答案 3 :(得分:1)

而不是

try {
    is = url.openStream();
} catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    exitprint();
}

你可以尝试设置更长的超时,你仍然可以通过捕获it

来处理超时异常
try {
    URLConnection con= url.openConnection();
    con.setConnectTimeout(5000); 
    con.setReadTimeout(50000);
    BufferedReader in = new BufferedReader(
        new InputStreamReader(con.getInputStream()));
    String inputLine;
    while ((inputLine = in.readLine()) != null) 
        System.out.println(inputLine);
    in.close();
} catch (SocketTimeoutException e) {
    //here you can still handle timeout like try again under certain conditions
}

答案 4 :(得分:1)

我认为AOP和Java注释是一个不错的选择。我建议使用jcabi-aspects中的读取机制:

@RetryOnFailure(attempts = 2, delay = 10)
public String load(URL url) {
  return url.openConnection().getContent();
}