Je souhaite définir les délais de connexion pour un service de repos utilisé par mon application Web. J'utilise Spring's RestTemplate pour parler à mon service. J'ai fait des recherches et j'ai trouvé et utilisé le XML ci-dessous (dans mon application XML) qui, je crois, est destiné à définir le délai d'attente. J'utilise Spring 3.0.
J'ai également vu le même problème ici Configuration du délai d'attente pour les services Web Spring avec RestTemplate mais les solutions ne semblent pas être que clean, je préférerais définir les valeurs de délai d'attente via Spring config
<bean id="RestOperations" class="org.springframework.web.client.RestTemplate">
<constructor-arg>
<bean class="org.springframework.http.client.CommonsClientHttpRequestFactory">
<property name="readTimeout" value="${restURL.connectionTimeout}" />
</bean>
</constructor-arg>
</bean>
Il semble que quoi que je définisse le readTimeout, j'obtienne ce qui suit:
Câble réseau déconnecté: Attend environ 20 secondes et signale l'exception suivante:
org.springframework.web.client.ResourceAccessException: erreur d'E/S: aucune route vers l'hôte: connect; L'exception imbriquée est Java.net.NoRouteToHostException: aucune route vers l'hôte: connect
Url incorrect alors 404 renvoyé par le service de repos: Attend environ 10 secondes et signale l'exception suivante:
org.springframework.web.client.HttpClientErrorException: 404 Introuvable
Mes besoins nécessitent des délais d'attente plus courts et je dois donc pouvoir les modifier. Des idées sur ce que je fais mal?
Merci beaucoup.
J'ai finalement eu ce travail.
Je pense que le fait que notre projet ait deux versions différentes du fichier jar commons-httpclient n'aidait pas. Une fois que j'ai résolu ce problème, j'ai découvert que vous pouviez faire deux choses ...
Dans le code, vous pouvez mettre ce qui suit:
HttpComponentsClientHttpRequestFactory rf =
(HttpComponentsClientHttpRequestFactory) restTemplate.getRequestFactory();
rf.setReadTimeout(1 * 1000);
rf.setConnectTimeout(1 * 1000);
La première fois que ce code est appelé, il définit le délai d'expiration de la classe HttpComponentsClientHttpRequestFactory
utilisée par la variable RestTemplate
. Par conséquent, tous les appels ultérieurs passés par RestTemplate
utiliseront les paramètres de délai d'attente définis ci-dessus.
Ou la meilleure option est de faire ceci:
<bean id="RestOperations" class="org.springframework.web.client.RestTemplate">
<constructor-arg>
<bean class="org.springframework.http.client.HttpComponentsClientHttpRequestFactory">
<property name="readTimeout" value="${application.urlReadTimeout}" />
<property name="connectTimeout" value="${application.urlConnectionTimeout}" />
</bean>
</constructor-arg>
</bean>
Où j'utilise l'interface RestOperations
dans mon code et récupère les valeurs de délai d'attente à partir d'un fichier de propriétés.
Pour Spring Boot> = 1.4
@Configuration
public class AppConfig
{
@Bean
public RestTemplate restTemplate(RestTemplateBuilder restTemplateBuilder)
{
return restTemplateBuilder
.setConnectTimeout(...)
.setReadTimeout(...)
.build();
}
}
Pour Spring Boot <= 1.3
@Configuration
public class AppConfig
{
@Bean
@ConfigurationProperties(prefix = "custom.rest.connection")
public HttpComponentsClientHttpRequestFactory customHttpRequestFactory()
{
return new HttpComponentsClientHttpRequestFactory();
}
@Bean
public RestTemplate customRestTemplate()
{
return new RestTemplate(customHttpRequestFactory());
}
}
puis dans votre application.properties
custom.rest.connection.connection-request-timeout=...
custom.rest.connection.connect-timeout=...
custom.rest.connection.read-timeout=...
Cela fonctionne parce que HttpComponentsClientHttpRequestFactory
a des paramètres publics connectionRequestTimeout
, connectTimeout
et readTimeout
et @ConfigurationProperties
les définit pour vous.
Pour Spring 4.1 ou Spring 5 sans Spring Boot utilisez @Configuration
au lieu de XML
@Configuration
public class AppConfig
{
@Bean
public RestTemplate customRestTemplate()
{
HttpComponentsClientHttpRequestFactory httpRequestFactory = new HttpComponentsClientHttpRequestFactory();
httpRequestFactory.setConnectionRequestTimeout(...);
httpRequestFactory.setConnectTimeout(...);
httpRequestFactory.setReadTimeout(...);
return new RestTemplate(httpRequestFactory);
}
}
Cette question est le premier lien pour une recherche dans Spring Boot. Par conséquent, il serait bon de mettre ici la solution recommandée dans la documentation officielle . Spring Boot a son propre bean pratique RestTemplateBuilder :
@Bean
public RestTemplate restTemplate(
RestTemplateBuilder restTemplateBuilder) {
return restTemplateBuilder
.setConnectTimeout(500)
.setReadTimeout(500)
.build();
}
La création manuelle d'instances RestTemplate est une approche potentiellement gênante, car d'autres beans configurés automatiquement ne sont pas injectés dans des instances créées manuellement.
Voici un moyen très simple de définir le délai d'attente:
RestTemplate restTemplate = new RestTemplate(getClientHttpRequestFactory());
private ClientHttpRequestFactory getClientHttpRequestFactory() {
int timeout = 5000;
HttpComponentsClientHttpRequestFactory clientHttpRequestFactory =
new HttpComponentsClientHttpRequestFactory();
clientHttpRequestFactory.setConnectTimeout(timeout);
return clientHttpRequestFactory;
}
Voici mes 2 cents. Rien de nouveau, mais quelques explications, améliorations et code plus récent.
Par défaut, RestTemplate
a un délai d'expiration infini . Il existe deux types de délais d'expiration: le délai de connexion et le délai de lecture. Par exemple, je pouvais me connecter au serveur mais je ne pouvais pas lire les données. L'application était en suspens et vous n'avez aucune idée de ce qui se passe.
Je vais utiliser des annotations, qui sont préférables de nos jours à XML.
@Configuration
public class AppConfig {
@Bean
public RestTemplate restTemplate() {
var factory = new SimpleClientHttpRequestFactory();
factory.setConnectTimeout(3000);
factory.setReadTimeout(3000);
return new RestTemplate(factory);
}
}
Ici, nous utilisons SimpleClientHttpRequestFactory
pour définir la connexion et le délai de lecture .. Il est ensuite transmis au constructeur de RestTemplate
.
@Configuration
public class AppConfig {
@Bean
public RestTemplate restTemplate(RestTemplateBuilder builder) {
return builder
.setConnectTimeout(Duration.ofMillis(3000))
.setReadTimeout(Duration.ofMillis(3000))
.build();
}
}
Dans la deuxième solution, nous utilisons la variable RestTemplateBuilder
. Notez également les paramètres des deux méthodes: elles prennent Duration
. Les méthodes surchargées prenant directement des millisecondes sont maintenant obsolètes.
Edit Testé avec Spring Boot 2.1.0 et Java 11.
J'ai eu un scénario similaire, mais il était également nécessaire de définir un proxy. La façon la plus simple de procéder était d’étendre la variable SimpleClientHttpRequestFactory
pour faciliter le paramétrage du proxy (différents proxy pour les non-prod vs prod). Cela devrait quand même fonctionner même si vous n’avez pas besoin du proxy. Ensuite, dans ma classe étendue, je substitue la méthode openConnection(URL url, Proxy proxy)
, en utilisant la même chose que source , mais en définissant simplement les délais d'attente avant de retourner.
@Override
protected HttpURLConnection openConnection(URL url, Proxy proxy) throws IOException {
URLConnection urlConnection = proxy != null ? url.openConnection(proxy) : url.openConnection();
Assert.isInstanceOf(HttpURLConnection.class, urlConnection);
urlConnection.setConnectTimeout(5000);
urlConnection.setReadTimeout(5000);
return (HttpURLConnection) urlConnection;
}