在 Java 中超时重试连接
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7312794/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Retry a connection on timeout in Java
提问by InsanityOnABun
I have a method (below) that pulls down and returns the source of a webpage as a String. It all works fine and dandy, but when the connection times out, the program throws an exception and exits. Is there a better method to do this that would allow it to try again on timeout, or is there a way to do it within this method?
我有一个方法(如下)可以下拉并以字符串形式返回网页的源。一切正常,但当连接超时时,程序会抛出异常并退出。有没有更好的方法来做到这一点,让它在超时时再次尝试,或者有没有办法在这个方法中做到这一点?
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();
}
采纳答案by aioobe
Here's a refactoring of your code that should retry the download N
times. Haven't tested it though, but it should kick you off in the right direction.
这是您的代码的重构,应该重试下载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");
}
回答by Kevin
Write a wrapper function around it and allow the connect exception to propogate out. Then you can loop calling your existing function while you receive connect exception upto some max retries.
围绕它编写一个包装函数并允许连接异常传播出去。然后,您可以在收到连接异常时循环调用现有函数,直至达到最大重试次数。
This is better than embedding a for loop in your existing function because it logically separates retry logic from mainline code. And it's easier to read and understand as a result.
这比在现有函数中嵌入 for 循环要好,因为它在逻辑上将重试逻辑与主线代码分开。因此,它更易于阅读和理解。
回答by andronikus
You could put the whole thing in a while
loop:
你可以把整个事情放在一个while
循环中:
while (true) {
try {
...
} catch (IOException e) {
continue;
}
return buffer.toString();
}
The return
statement will break you out of the loop. You might also want to keep track of the number of attempts and stop after 5-10, for politeness, but that's the basic shape of it.
该return
语句将使您跳出循环。为了礼貌起见,您可能还想记录尝试次数并在 5-10 次后停止,但这是它的基本形状。
Edit
编辑
The better version, based on comments:
更好的版本,基于评论:
int retries = 10;
for (int i = 0 ; i < retries ; i++) {
try {
...
} catch (IOException e) {
continue;
}
return buffer.toString();
}
回答by bpgergo
Instead of
代替
try {
is = url.openStream();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
exitprint();
}
you can try set longer timeout and you can still handle timeout exception by catching 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
}
回答by yegor256
I think AOP and Java annotations is a good option. I would recommend to use a read-made mechanism from jcabi-aspects:
我认为 AOP 和 Java 注释是一个不错的选择。我会建议使用jcabi-aspects 中的一种只读机制:
@RetryOnFailure(attempts = 2, delay = 10)
public String load(URL url) {
return url.openConnection().getContent();
}