with mvc enablewebsecurity spring rest timeout resttemplate

mvc - spring security web



Spring RestTemplate tiempo de espera (5)

Me gustaría establecer los tiempos de espera de conexión para un servicio de descanso utilizado por mi aplicación web. Estoy usando Spring''s RestTemplate para hablar con mi servicio. Investigué un poco y encontré y utilicé el xml a continuación (en mi aplicación xml), que creo que está destinado a establecer el tiempo de espera. Estoy usando Spring 3.0.

También he visto el mismo problema aquí Configuración de tiempo de espera para los servicios web de primavera con RestTemplate pero las soluciones no parecen tan limpias , prefiero establecer los valores de tiempo de espera a través de 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>

Parece que cualquier cosa que establezca el readTimeout es que obtengo lo siguiente:

Cable de red desconectado: espera unos 20 segundos e informa después de la excepción:

org.springframework.web.client.ResourceAccessException: Error de E / S: No hay ruta al host: connect; la excepción anidada es java.net.NoRouteToHostException: no hay ruta al host: connect

La URL es incorrecta, por lo que el servicio de recuperación devuelve 404: Espera aproximadamente 10 segundos e informa de la siguiente excepción:

org.springframework.web.client.HttpClientErrorException: 404 no encontrado

Mis requisitos requieren tiempos de espera más cortos, así que necesito poder cambiarlos. ¿Alguna idea de lo que estoy haciendo mal?

Muchas gracias.


Aquí hay una forma muy simple de configurar el tiempo de espera:

RestTemplate restTemplate = new RestTemplate(getClientHttpRequestFactory()); private ClientHttpRequestFactory getClientHttpRequestFactory() { int timeout = 5000; HttpComponentsClientHttpRequestFactory clientHttpRequestFactory = new HttpComponentsClientHttpRequestFactory(); clientHttpRequestFactory.setConnectTimeout(timeout); return clientHttpRequestFactory; }


Esta pregunta es el primer enlace para una búsqueda de Spring Boot, por lo tanto, sería genial poner aquí la solución recomendada en la documentación oficial . Spring Boot tiene su propio bean convenience RestTemplateBuilder :

@Bean public RestTemplate restTemplate( RestTemplateBuilder restTemplateBuilder) { return restTemplateBuilder .setConnectTimeout(500) .setReadTimeout(500) .build(); }

La creación manual de instancias de RestTemplate es un enfoque potencialmente problemático porque otros beans configurados automáticamente no se están inyectando en instancias creadas manualmente.


Finalmente conseguí que esto funcionara.

Creo que el hecho de que nuestro proyecto tuviera dos versiones diferentes de commons-httpclient jar no ayudaba. Una vez que resolví eso, descubrí que puedes hacer dos cosas ...

En el código puedes poner lo siguiente:

HttpComponentsClientHttpRequestFactory rf = (HttpComponentsClientHttpRequestFactory) restTemplate.getRequestFactory(); rf.setReadTimeout(1 * 1000); rf.setConnectTimeout(1 * 1000);

La primera vez que se llama a este código establecerá el tiempo de espera para la clase HttpComponentsClientHttpRequestFactory utilizada por RestTemplate . Por lo tanto, todas las llamadas posteriores realizadas por RestTemplate utilizarán la configuración de tiempo de espera definida anteriormente.

O la mejor opción es hacer esto:

<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>

Donde uso la interfaz RestOperations en mi código y obtengo los valores de tiempo de espera de un archivo de propiedades.


Para Spring Boot> = 1.4

@Configuration public class AppConfig { @Bean public RestTemplate restTemplate(RestTemplateBuilder restTemplateBuilder) { return restTemplateBuilder .setConnectTimeout(...) .setReadTimeout(...) .build(); } }

Para 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()); } }

luego en su application.properties

custom.rest.connection.connection-request-timeout=... custom.rest.connection.connect-timeout=... custom.rest.connection.read-timeout=...

Esto funciona porque HttpComponentsClientHttpRequestFactory tiene los setters públicos connectionRequestTimeout , connectTimeout , y readTimeout y @ConfigurationProperties establece por usted.

Para Spring 4 o Spring 5 sin Spring Boot usando @Configuration lugar de XML

@Configuration public class AppConfig { @Bean public RestTemplate customRestTemplate() { HttpComponentsClientHttpRequestFactory httpRequestFactory = new HttpComponentsClientHttpRequestFactory(); httpRequestFactory.setConnectionRequestTimeout(...); httpRequestFactory.setConnectTimeout(...); httpRequestFactory.setReadTimeout(...); return new RestTemplate(httpRequestFactory); } }


Tuve un escenario similar, pero también se requirió establecer un Proxy. La forma más simple que pude ver para hacer esto fue extender el SimpleClientHttpRequestFactory para la facilidad de configuración del proxy (diferentes proxies para non-prod vs prod). Esto aún debería funcionar, aunque no requiera el proxy. Luego, en mi clase extendida, openConnection(URL url, Proxy proxy) el openConnection(URL url, Proxy proxy) , usando el mismo que el de source , pero solo establezco los tiempos de espera antes de volver.

@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; }