配置属性类

@Data  
@ConfigurationProperties(prefix = "sys.http.client.config")
public class HttpClientConfigProperties {
/**
* 最大连接池连接数量(n个url)
*/
private Integer poolMaxTotalConn = 400;

/**
* 最大单个路由(url)连接数量
*/
private Integer perRouterMaxConn = 100;

/**
* 连接超时时间 ms
*/ private Integer connTimeOut = 3000;

/**
* 读取超时SocketTimeOut ms
*/ private Integer connReadTimeOut = 5000;

/**
* 连接池获取请求的最大等待时间 ms
*/ private Integer poolConnReqTimeOut = 200;

/**
* 长连接保持时间 ms
*/ private Long keepAliveTime = 0L;

/**
* 配置保持长连接的域名Host
*/ private Map<String,Long> keepAliveTargetHost;

/**
* 连接默认HTTP字符集
*/
private String charSet = "UTF-8";

/**
* 支持的SSL协议
*/
private String[] supportsSslProtocol =new String[]{"SSLv3","SSLv2Hello","TLSv1","TLSv1.1","TLSv1.2"};

}

RestTemplate自定义配置

@Configuration  
@EnableConfigurationProperties({HttpClientConfigProperties.class})
@ConditionalOnClass({RestTemplate.class})
@Slf4j
public class RestTemplateConfig {

@Autowired
HttpClientConfigProperties httpClientConfigProperties;

/**
* <b>注入默认RestTemplate<b/>
* * @return RestTemplate.class
*/ @Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
/**
* <b>注入自定义连接工厂的RestTemplate<b/>
* * @return RestTemplate.class
*/ @Bean("customShuShuoRestTemplate")
public RestTemplate customRestTemplate(ClientHttpRequestFactory httpRequestFactory) {
RestTemplate restTemplate = new RestTemplate(httpRequestFactory);
//设置字符集 - 重新设置StringHttpMessageConverter字符集
List<HttpMessageConverter<?>> converterList = restTemplate.getMessageConverters();
HttpMessageConverter<?> converterTarget = null;
for (HttpMessageConverter<?> item : converterList) {
if (StringHttpMessageConverter.class == item.getClass()) {
converterTarget = item;
break;
} } if (null != converterTarget) {
converterList.remove(converterTarget);
} Charset defaultCharset = Charset.forName(httpClientConfigProperties.getCharSet());
converterList.add(1, new StringHttpMessageConverter(defaultCharset));
//设置错误处理器
restTemplate.setErrorHandler(new DefaultResponseErrorHandler());
List<ClientHttpRequestInterceptor> clientHttpRequestInterceptors = new LinkedList<>();
clientHttpRequestInterceptors.add(new HttpSendInterceptor());
restTemplate.setInterceptors(clientHttpRequestInterceptors);
return restTemplate;
}
/**
* <b>初始化HttpClient连接工厂</b>
* * @return ClientHttpRequestFactory
*/ @Bean
public ClientHttpRequestFactory clientHttpRequestFactory(HttpClient httpClient) {
//检查配置类信息
ConfigCheckUtils.checkHttpClientConfig(httpClientConfigProperties);
//初始化链接工厂,设置默认的链接对象
HttpComponentsClientHttpRequestFactory httpComponentsClientHttpRequestFactory = new HttpComponentsClientHttpRequestFactory();
httpComponentsClientHttpRequestFactory.setHttpClient(httpClient);
//设置读取超时
httpComponentsClientHttpRequestFactory.setReadTimeout(httpClientConfigProperties.getConnReadTimeOut());
//设置从链接池获取链接超时
httpComponentsClientHttpRequestFactory.setConnectionRequestTimeout(httpClientConfigProperties.getPoolConnReqTimeOut());
//设置连接超时,与服务握手
httpComponentsClientHttpRequestFactory.setConnectTimeout(httpClientConfigProperties.getConnTimeOut());
return httpComponentsClientHttpRequestFactory;
}
/**
* 设置HTTP池化连接池
* @return 连接池
* @throws NoSuchAlgorithmException 没有这个算法
* @throws KeyStoreException 密码存储异常
* @throws KeyManagementException 密码管理器异常
*/
@Bean
public HttpClientConnectionManager poolingHttpClientConnectionManager() throws NoSuchAlgorithmException, KeyStoreException, KeyManagementException {
Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
.register("http", PlainConnectionSocketFactory.INSTANCE)
.register("https", createSslConnectionFactory())
.build();
//init httpClient Pool
PoolingHttpClientConnectionManager poolingHttpClientConnectionManager = new PoolingHttpClientConnectionManager(registry);
//配置连接池
poolingHttpClientConnectionManager.setDefaultMaxPerRoute(httpClientConfigProperties.getPerRouterMaxConn());
poolingHttpClientConnectionManager.setMaxTotal(httpClientConfigProperties.getPoolMaxTotalConn());
return poolingHttpClientConnectionManager;
}
/**
* <b>创建HTTPClient自定义对象</b>
* * @return HttpClient
*/ @Bean
public HttpClient httpClient(HttpClientConnectionManager httpClientConnectionManager) {
//init httpclient
HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
//设置连接管理器
httpClientBuilder.setConnectionManager(httpClientConnectionManager);
//设置重试,默认没有开启
httpClientBuilder.setRetryHandler(DefaultHttpRequestRetryHandler.INSTANCE);
//设置 请求头
httpClientBuilder.setDefaultHeaders(defaultHeaders());
//设置连接策略
httpClientBuilder.setKeepAliveStrategy(connectionKeepAliveStrategy());
return httpClientBuilder.build();
}

/**
* <b>设置Http长连接处理策略</b>
* * @return ConnectionKeepAliveStrategy
*/ @Bean
public ConnectionKeepAliveStrategy connectionKeepAliveStrategy() {
return (response, context) -> {
// Honor 'keep-alive' header
HeaderElementIterator it = new BasicHeaderElementIterator(
response.headerIterator(HTTP.CONN_KEEP_ALIVE));
while (it.hasNext()) {
HeaderElement he = it.nextElement();
log.info("HeaderElement:{}", JSON.toJSONString(he));
String param = he.getName();
String value = he.getValue();
if (value != null && "timeout".equalsIgnoreCase(param)) {
try {
return Long.parseLong(value) * 1000;
} catch (NumberFormatException e) {
log.error("解析长连接过期时间异常", e);
} } } HttpHost target = (HttpHost) context.getAttribute(HttpCoreContext.HTTP_TARGET_HOST);
//如果请求Host存在配置的连接时间就用配置的,没配就是默认
Optional<Map.Entry<String, Long>> any = Optional.ofNullable(httpClientConfigProperties.getKeepAliveTargetHost()).orElseGet(HashMap::new)
.entrySet().stream().filter(
e -> e.getKey().equalsIgnoreCase(target.getHostName())).findAny();
return any.map(Map.Entry::getValue).orElse(httpClientConfigProperties.getKeepAliveTime());
}; }

/**
* <b>默认请求头</b>
* * @return List<Header> headers
*/ private List<Header> defaultHeaders() {
ArrayList<Header> headers = new ArrayList<>();
headers.add(new BasicHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.5112.81 Safari/537.36 Edg/104.0" +
".1293.54"));
headers.add(new BasicHeader("Accept-Encoding", "gzip,deflate"));
headers.add(new BasicHeader("Accept-Language", "zh-CN,en-US"));
headers.add(new BasicHeader("Connection", "Keep-Alive"));
headers.add(new BasicHeader("Content-Type", "application/json"));
return headers;
}

/**
* <b>配置绕过不安全HTTPS协议连接工厂</b>
* * @return ConnectionSocketFactory异常
* @throws NoSuchAlgorithmException 找不到指定算法
* @throws KeyManagementException 没有键值管理器异常
* @throws KeyStoreException ssl键存储吧异常
*/
private ConnectionSocketFactory createSslConnectionFactory() throws NoSuchAlgorithmException, KeyStoreException, KeyManagementException {
//init ssl上下文 加载信任证书
SSLContextBuilder sslContextBuilder = new SSLContextBuilder();
//重写TrustStrategy信任策略
sslContextBuilder.loadTrustMaterial(null, (chain, authType) -> true);
SSLContext sslContext = sslContextBuilder.build();
//create SSL connFactory
return new SSLConnectionSocketFactory(sslContext, httpClientConfigProperties.getSupportsSslProtocol(), null, SSLConnectionSocketFactory.getDefaultHostnameVerifier());
}}