# 问题
http 请求发起后接收不到返回数据!!!【测试环境没出问题,发到正式环境就有问题】
项目中通过 restTemplate 发起请求:
| log.info("请求入参:{}",JSON.toJSONString(request)); |
| |
| HttpsClientRequestFactory factory = new HttpsClientRequestFactory(); |
| factory.setConnectTimeout(60 * 1000); |
| factory.setReadTimeout(5 * 60 * 1000); |
| RestTemplate restTemplate = new RestTemplate(factory); |
| Result<InventoryResult> result = restTemplate.postForObject(address.concat(inventoryUrl), request, Result.class); |
| log.info("库存同步,返回数据: {}", result); |
http 请求入参:{data=[{ productStatus=10,skuCode=null}], messageId=ewpfpr1t6ey5r6qj0su0w1h6rt73hr,token=vgvU5EJKuZbuHii7WH6pTINp40ZRicaqLz4dq5P7L6pDzWir8EEGZhCKPucQjljsw69EHasEy+iJfdTofDg==}
# 解决方式
# 第一种
- 添加 HttpsClientRequestFactory 类,并继承 SimpleClientHttpRequestFactory
| |
| * 兼容调 Https 接口 |
| */ |
| public class HttpsClientRequestFactory extends SimpleClientHttpRequestFactory { |
| |
| @Override |
| protected void prepareConnection(HttpURLConnection connection, String httpMethod) |
| throws IOException { |
| if (connection instanceof HttpsURLConnection) { |
| prepareHttpsConnection((HttpsURLConnection) connection); |
| } |
| super.prepareConnection(connection, httpMethod); |
| } |
| |
| private void prepareHttpsConnection(HttpsURLConnection connection) { |
| connection.setHostnameVerifier(new SkipHostnameVerifier()); |
| try { |
| connection.setSSLSocketFactory(createSslSocketFactory()); |
| } |
| catch (Exception ex) { |
| |
| } |
| } |
| |
| private SSLSocketFactory createSslSocketFactory() throws Exception { |
| SSLContext context = SSLContext.getInstance("TLS"); |
| context.init(null, new TrustManager[] { new SkipX509TrustManager() }, |
| new SecureRandom()); |
| return context.getSocketFactory(); |
| } |
| |
| private class SkipHostnameVerifier implements HostnameVerifier { |
| |
| @Override |
| public boolean verify(String s, SSLSession sslSession) { |
| return true; |
| } |
| |
| } |
| |
| private static class SkipX509TrustManager implements X509TrustManager { |
| |
| @Override |
| public X509Certificate[] getAcceptedIssuers() { |
| return new X509Certificate[0]; |
| } |
| |
| @Override |
| public void checkClientTrusted(X509Certificate[] chain, String authType) { |
| } |
| |
| @Override |
| public void checkServerTrusted(X509Certificate[] chain, String authType) { |
| } |
| |
| } |
| } |
- 使用 restTemplate 发起请求前先设置连接和超时时间或者通过容器加载配置类然后设置超时时间
| |
| HttpsClientRequestFactory factory = new HttpsClientRequestFactory(); |
| factory.setConnectTimeout(60 * 1000); |
| factory.setReadTimeout(5 * 60 * 1000); |
| RestTemplate restTemplate = new RestTemplate(factory); |
| BaseResult<QueryInventoryResult> result = restTemplate.postForObject(address.concat(inventoryUrl), request, Result.class); |
| @Configuration |
| public class RestConfig { |
| |
| |
| @Value("${rest.connectTimeout:60000}") |
| private int connectTimeout; |
| |
| |
| @Value("${rest.readTimeout:300000}") |
| private int readTimeout; |
| |
| @Bean |
| public RestTemplate restTemplate() { |
| SimpleClientHttpRequestFactory simpleClientHttpRequestFactory = new SimpleClientHttpRequestFactory(); |
| simpleClientHttpRequestFactory.setConnectTimeout(connectTimeout); |
| simpleClientHttpRequestFactory.setReadTimeout(readTimeout); |
| RestTemplate restTemplate = new RestTemplate(simpleClientHttpRequestFactory); |
| return restTemplate; |
| } |
# 第二种
| @Configuration |
| public class RestConfig { |
| |
| |
| @Value("${rest.connectTimeout:60000}") |
| private int connectTimeout; |
| |
| |
| @Value("${rest.readTimeout:300000}") |
| private int readTimeout; |
| |
| @Value("${rest.connectionRequestTimeout:300000}") |
| private int connectionRequestTimeout; |
| |
| |
| * 使用 HttpComponentsClientHttpRequestFactory 创建 http 请求(推荐) |
| */ |
| @Bean |
| public RestTemplate restTemplate() { |
| HttpComponentsClientHttpRequestFactory httpRequestFactory = new HttpComponentsClientHttpRequestFactory(); |
| httpRequestFactory.setConnectionRequestTimeout(connectionRequestTimeout); |
| httpRequestFactory.setConnectTimeout(connectTimeout); |
| httpRequestFactory.setReadTimeout(readTimeout); |
| return new RestTemplate(httpRequestFactory); |
| |
| } |
| } |
# 第三种(基于第二种升级)
| @Configuration |
| public class RestConfig { |
| |
| |
| |
| * 高并发采用 HttpClient 连接池 |
| */ |
| @Bean |
| public RestTemplate restTemplate() { |
| return new RestTemplate(httpRequestFactory()); |
| } |
| |
| |
| @Bean |
| public ClientHttpRequestFactory httpRequestFactory() { |
| return new HttpComponentsClientHttpRequestFactory(httpClient()); |
| } |
| |
| |
| @Bean |
| public HttpClient httpClient() { |
| Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create() |
| .register("http", PlainConnectionSocketFactory.getSocketFactory()) |
| .register("https", SSLConnectionSocketFactory.getSocketFactory()) |
| .build(); |
| PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(registry); |
| |
| connectionManager.setMaxTotal(1000); |
| |
| connectionManager.setDefaultMaxPerRoute(100); |
| |
| connectionManager.setValidateAfterInactivity(200); |
| RequestConfig requestConfig = RequestConfig.custom() |
| .setSocketTimeout(30000) |
| .setConnectTimeout(20000) |
| .setConnectionRequestTimeout(1000) |
| .build(); |
| return HttpClientBuilder.create() |
| .setDefaultRequestConfig(requestConfig) |
| .setConnectionManager(connectionManager) |
| .evictIdleConnections(2, TimeUnit.SECONDS) |
| .build(); |
| } |
| } |