0. 原因
我调用第三方接口时,第三方接口抛出异常!restTemplate 接收到异常之后
启用了自己的异常处理!
导致了第三方抛出的错误信息被覆盖,调用方不能准确的获取错误消息提示
1. 直接new
private static RestTemplate restTemplate = new RestTemplate();
// 错误处理
restTemplate.setErrorHandler(new NoErrorResultErrorHandler());
Map<String,Object> respMap = restTemplate.exchange(url, HttpMethod.POST, requestEntity, Map.class).getBody();
2. 如果使用配置类
package com.cr.code.eco.ecoapi.config;
import org.apache.http.client.HttpClient;
import org.apache.http.impl.client.DefaultConnectionKeepAliveStrategy;
import org.apache.http.impl.client.DefaultHttpRequestRetryHandler;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpStatus;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.DefaultResponseErrorHandler;
import org.springframework.web.client.RestTemplate;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
/**
*
* 解决RestTemplate 中高并发情况下Socket InteAddress 用尽
* @参考: https://blog.csdn.net/qq_27217017/article/details/98601893
*
* @author tn
* @version 1
* @ClassName RestTemplateConfig
* @description RestTemplate跟换底层
* 高频且短的大量Request请求,控制 Request的请求量,不会跑出IntAddress use out的异常
*
* @date 2020/7/26 3:01
*/
public class RestTemplateConfig {
private static RestTemplate restTemplate;
static {
// 长链接保持时间长度20秒
PoolingHttpClientConnectionManager poolingHttpClientConnectionManager =
new PoolingHttpClientConnectionManager(20, TimeUnit.SECONDS);
// 设置最大链接数
poolingHttpClientConnectionManager.setMaxTotal(2*getMaxCpuCore() + 3 );
// 单路由的并发数
poolingHttpClientConnectionManager.setDefaultMaxPerRoute(2*getMaxCpuCore());
HttpClientBuilder httpClientBuilder = HttpClients.custom();
httpClientBuilder.setConnectionManager(poolingHttpClientConnectionManager);
// 重试次数3次,并开启
httpClientBuilder.setRetryHandler(new DefaultHttpRequestRetryHandler(3,true));
HttpClient httpClient = httpClientBuilder.build();
// 保持长链接配置,keep-alive
httpClientBuilder.setKeepAliveStrategy(new DefaultConnectionKeepAliveStrategy());
HttpComponentsClientHttpRequestFactory httpComponentsClientHttpRequestFactory = new HttpComponentsClientHttpRequestFactory(httpClient);
// 链接超时配置 5秒
httpComponentsClientHttpRequestFactory.setConnectTimeout(5000);
// 连接读取超时配置
// httpComponentsClientHttpRequestFactory.setReadTimeout(10000);
// 连接池不够用时候等待时间长度设置,分词那边 500毫秒 ,我们这边设置成1秒
httpComponentsClientHttpRequestFactory.setConnectionRequestTimeout(3000);
// 缓冲请求数据,POST大量数据,可以设定为true 我们这边机器比较内存较大
httpComponentsClientHttpRequestFactory.setBufferRequestBody(true);
restTemplate = new RestTemplate();
restTemplate.setRequestFactory(httpComponentsClientHttpRequestFactory);
//注意:如果不重写 handleError http抛出的异常会直接转发给前端项目中就获取不了接口返回值了
restTemplate.setErrorHandler(new DefaultResponseErrorHandler(){
@Override
public void handleError(ClientHttpResponse response) throws IOException {
if(response.getStatusCode() == HttpStatus.OK){
super.handleError(response);
}
}
});
}
public static RestTemplate getRestTemplate(){
return restTemplate;
}
private static int getMaxCpuCore(){
int cpuCore = Runtime.getRuntime().availableProcessors();
return cpuCore;
}
}
使用:
/**
* http调用
*/
private RestTemplate restTemplate = RestTemplateConfig.getRestTemplate();
/**
* @return
*/
private List<EnvironmentDetectionResponseVo> test(){
String body = restTemplate.getForEntity("http://url",String.class).getBody();
JSONArray jsonArray = JSON.parseArray(body);
EnvironmentDetectionResponseVo[] EnvironmentDetectionResponseVo = jsonArray.toJavaObject(EnvironmentDetectionResponseVo[].class);
return Arrays.asList(EnvironmentDetectionResponseVo);
}