RestTemplate -- 默认超时时间

43

使用Spring的RestTemplate时,默认超时时间是多少?

例如,我像这样调用Web服务:

RestTemplate restTemplate = new RestTemplate();
String response = restTemplate.getForObject("http://webservice.com/item/3455", String.class);

RestTemplate 是否有内置的超时值?我不打算更改超时值,但我希望确保每个请求都有合理的超时时间。

4个回答

36

明确回答问题:

默认超时时间是无限的。

RestTemplate默认使用SimpleClientHttpRequestFactory,而SimpleClientHttpRequestFactory又使用HttpURLConnection。

HttpURLConnection的默认超时时间是0——即永不超时,除非通过这些属性设置了超时时间:

-Dsun.net.client.defaultConnectTimeout=TimeoutInMiliSec 
-Dsun.net.client.defaultReadTimeout=TimeoutInMiliSec 

有没有API可以查询当前设置的值?我可以看到HttpComponentsClientHttpRequestFactory上的setter来设置值,但是没有相应的getter直接查询这些值? - Kevin Hooke
1
这是唯一对我有效的方法。我尝试通过API为HttpComponentsClientHttpRequestFactory设置超时时间,但没有成功。我不得不将上述值作为运行时参数传递(Spring Boot - 2.1.5)。 - hashcoder

26

我认为你可以使用SimpleClientHttpRequestFactory来设置超时参数。可以通过构造函数或setter方法将SimpleClientHttpRequestFactory的实例设置到rest模板中。

默认情况下,RestTemplate使用SimpleClientHttpRequestFactory,因此您可以直接将值设置给restTemplate。


1
谢谢。我查看了SimpleClientHttpRequestFactory的文档,它提到“默认超时时间是系统的默认超时时间”。这是什么意思? - saravana_pc
2
我已经查看了SimpleClientHttpRequestFactory的源代码,发现默认值为-1,分别对应读取超时和连接超时。我认为这里的默认值意味着HTTP依赖于URLConnection,因此默认的超时设置将取决于JDK。 - Jigar Parekh
URLConnection的默认超时时间是无限的。这是否意味着RestTemplate也具有无限超时值? - saravana_pc
4
默认情况下是启用的,查看链接。您可以使用系统属性设置系统超时时间。 - Jigar Parekh

12

Spring-Android RestTemplate的一个不错的特性是根据Android系统版本使用适当的(由Google推荐的)RequestFactory实现。

Google建议在Gingerbread(版本2.3)及更高版本上使用J2SE设施,而较早的版本应该使用HttpComponents HttpClient。基于此建议,RestTemplate会检查您的应用程序运行的Android版本并使用适当的ClientHttpRequestFactory。

因此,前面的答案并不完整,因为它没有考虑到HttpComponentsClientHttpRequestFactory(它被用于Android OS版本 < 2.3)。

我的解决方案大致如下:

public class MyRestTemplate extends RestTemplate {
    public MyRestTemplate() {
        if (getRequestFactory() instanceof SimpleClientHttpRequestFactory) {
            Log.d("HTTP", "HttpUrlConnection is used");
            ((SimpleClientHttpRequestFactory) getRequestFactory()).setConnectTimeout(10 * 1000);
            ((SimpleClientHttpRequestFactory) getRequestFactory()).setReadTimeout(10 * 1000);
        } else if (getRequestFactory() instanceof HttpComponentsClientHttpRequestFactory) {
            Log.d("HTTP", "HttpClient is used");
            ((HttpComponentsClientHttpRequestFactory) getRequestFactory()).setReadTimeout(10 * 1000);
            ((HttpComponentsClientHttpRequestFactory) getRequestFactory()).setConnectTimeout(10 * 1000);
        }
    }
}

感谢提供代码!我们如何为REST调用设置超时消息?因为我想在请求超时且服务器端没有结果和错误时显示一些消息。 - Aswathy P Krishnan
1
当您执行请求时,请捕获SocketTimeoutException或类似异常,并显示超时消息。 - agamov
谢谢您的评论! :) 我正在处理太多的rest调用,我正在使用android注释将它们组合在一个RestService接口中。所有这些rest调用都会抛出RestClientException。但是当我添加了IOException,其中包括SocketTimeoutException时,它要求我在每个rest调用处都进行处理。有没有办法在不更改每个rest调用的情况下处理它?我已经在这里发布了我的问题:https://dev59.com/X3LYa4cB1Zd3GeqPTRa0 - Aswathy P Krishnan

8
您可以在RestTemplate构造函数中使用ClientHttpRequestFactory参数:
private final int HTTP_CONNECT_TIMEOUT = 15000;
private final int HTTP_READ_TIMEOUT = 10000;

private ClientHttpRequestFactory getClientHttpRequestFactory() {
    HttpComponentsClientHttpRequestFactory clientHttpRequestFactory = new HttpComponentsClientHttpRequestFactory();
    clientHttpRequestFactory.setConnectTimeout(HTTP_CONNECT_TIMEOUT);
    clientHttpRequestFactory.setReadTimeout(HTTP_READ_TIMEOUT);
    return clientHttpRequestFactory;
}

当您需要一个新的RestTemplate时,请按照以下示例创建:

RestTemplate rt = new RestTemplate(getClientHttpRequestFactory());

问题是“默认超时时间是多少”,而不是如何设置超时值。 - Maykon Oliveira

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