解决存在网络隔离,首次连接请求被拒绝情况SocketException
首次请求超时情况SocketTimeoutException
无返回数据清空NoHttpResponseException进行重试
import org.apache.http.HttpEntityEnclosingRequest;
import org.apache.http.NoHttpResponseException;
import org.apache.http.client.HttpRequestRetryHandler;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.conn.ConnectTimeoutException;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;
import java.net.SocketException;
import java.net.SocketTimeoutException;
/**
* @ClassName: RestTemplateConfig
* @Description: 请求客户端配置
* <a href="https://www.saoniuhuo.com/question/detail-2235180.html">报异常首次连接超时等问题</a>
* @Application: 云上公交-应用管理平台
* @author: wangwenying
* @date: 2023/9/22
* @version: 1.0.0
* @Copyright: 智达信科技术股份有限公司版权所有。
*/
@Configuration
public class RestTemplateConfig {
private static final Logger logger = LoggerFactory.getLogger(RestTemplateConfig.class);
/**
* 连接超时时间
*/
private static final int CONNECT_TIMEOUT = 5000;
/**
* 连接管理器连接请求超时时间
*/
private static final int CONNECTION_MANAGER_CONNECTION_REQUEST_TIMEOUT = 0;
/**
* socket请求超时时间
*/
private static final int SOCKET_TIMEOUT = 5000;
/**
* 最大连接数
*/
private static final int MAX_TOTAL = 200;
/**
* 每个路由的最大连接数
*/
private static final int MAX_PER_ROUTE = 200;
/**
* 重试次数
*/
private static final int RETRY_TIMES = 3;
/**
* 重试延迟
*/
private static final int RETRY_INTERVAL_TIME = 1000;
/**
* @return {@link PoolingHttpClientConnectionManager }
* @Description 请求池
* @author wangwenying
* @date 2023-10-11
*/
@Bean
public PoolingHttpClientConnectionManager poolingHttpClientConnectionManager() {
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager();
connectionManager.setMaxTotal(MAX_TOTAL);
connectionManager.setDefaultMaxPerRoute(MAX_PER_ROUTE);
connectionManager.setValidateAfterInactivity(CONNECT_TIMEOUT);
return connectionManager;
}
/**
* @return {@link RequestConfig }
* @Description 请求配置
* @author wangwenying
* @date 2023-10-11
*/
@Bean
public RequestConfig requestConfig() {
return RequestConfig.custom()
.setConnectionRequestTimeout(CONNECTION_MANAGER_CONNECTION_REQUEST_TIMEOUT)
.setConnectTimeout(CONNECT_TIMEOUT)
.setSocketTimeout(SOCKET_TIMEOUT)
.build();
}
/**
* @param poolingHttpClientConnectionManager 池管理
* @param requestConfig 请求配置
* @return {@link CloseableHttpClient }
* @Description httpclient 配置
* @author wangwenying
* @date 2023-10-11
*/
@Bean
public CloseableHttpClient httpClient(PoolingHttpClientConnectionManager poolingHttpClientConnectionManager, RequestConfig requestConfig) {
HttpRequestRetryHandler handler = (exception, curRetryCount, context) -> {
logger.error("请求发生错误,错误信息ExceptionName:{}", exception.getClass().getName(), exception);
// curRetryCount 每一次都会递增,从1开始
if (curRetryCount > RETRY_TIMES) {
return false;
}
try {
//重试延迟
Thread.sleep((long) curRetryCount * RETRY_INTERVAL_TIME);
} catch (InterruptedException e) {
logger.error("延迟时间发生错误", e);
}
if (exception instanceof ConnectTimeoutException
|| exception instanceof NoHttpResponseException
|| exception instanceof SocketException
|| exception instanceof SocketTimeoutException) {
return true;
}
HttpClientContext clientContext = HttpClientContext.adapt(context);
org.apache.http.HttpRequest request = clientContext.getRequest();
// 如果请求被认为是幂等的,那么就重试。即重复执行不影响程序其他效果的
return !(request instanceof HttpEntityEnclosingRequest);
};
return HttpClientBuilder
.create()
.setConnectionManager(poolingHttpClientConnectionManager)
.setDefaultRequestConfig(requestConfig)
.setRetryHandler(handler)
.build();
}
/**
* @return {@link RestTemplate }
* @Description 请求5A接口配置
* @author wangwenying
* @date 2023-10-11
*/
@Bean("restTemplate")
public RestTemplate restTemplate() {
HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory();
factory.setHttpClient(httpClient(poolingHttpClientConnectionManager(), requestConfig()));
RestTemplate restTemplate = new RestTemplate();
restTemplate.setRequestFactory(factory);
return restTemplate;
}
}
标签:http,java,RestTemplate,return,重试,static,import,apache,org
From: https://www.cnblogs.com/stubborn-dude/p/17756839.html