HttpClent调用https请求时报错:javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sum.security.provider.certpath.SunCertPathBuilderException: unable to find valid…
解决方案:
创建一个共享连接池
static {
Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
.register("http", PlainConnectionSocketFactory.INSTANCE)
.register("https", createSSLConnSocketFactory())
.build();
// 设置连接池
connMgr = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
// 设置连接池大小
connMgr.setMaxTotal(500);
connMgr.setDefaultMaxPerRoute(connMgr.getMaxTotal());
RequestConfig.Builder configBuilder = RequestConfig.custom();
// 设置连接超时
configBuilder.setConnectTimeout(MAX_TIMEOUT);
// 设置读取超时
configBuilder.setSocketTimeout(MAX_TIMEOUT);
// 设置从连接池获取连接实例的超时
configBuilder.setConnectionRequestTimeout(MAX_TIMEOUT);
// 在提交请求之前 测试连接是否可用
configBuilder.setStaleConnectionCheckEnabled(true);
requestConfig = configBuilder.build();
}
创建SSL安全连接,并指定允许的协议类型
/**
* 创建SSL安全连接
*
* @return
*/
private static SSLConnectionSocketFactory createSSLConnSocketFactory() {
SSLConnectionSocketFactory sslsf = null;
try {
SSLContext ctx = SSLContext.getInstance("TLSv1.2");
X509TrustManager tm = new X509TrustManager() {
@Override
public void checkClientTrusted(X509Certificate[] chain,
String authType) throws CertificateException {
}
@Override
public void checkServerTrusted(X509Certificate[] chain,
String authType) throws CertificateException {
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return null;
}
};
ctx.init(null, new TrustManager[]{tm}, null);
sslsf = new SSLConnectionSocketFactory(ctx, new String[] { "SSLv3", "TLSv1", "TLSv1.1", "TLSv1.2" }, null,SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
} catch (GeneralSecurityException e) {
e.printStackTrace();
}
return sslsf;
}
注意使用共享链接池时,不能对httpClient进行close或者shutDown操作,否则下次使用连接池会抛出异常
public static String get(String url, Map<String,String> params, String charset){
CloseableHttpClient httpclient = HttpClients.custom().setConnectionManager(connMgr).setDefaultRequestConfig(requestConfig).build();
HttpGet hg = new HttpGet(url);
try {
responseStr = (String)httpclient.execute(hg, responseHandler);
} catch (ClientProtocolException e) {
logger.error("客户端连接协议错误", e);
} catch (Exception e) {
logger.error("IO操作异常", e);
} /*finally {
// 使用共享链接池的情况,不能关闭连接
abortConnection(hg, httpclient);
}*/
return responseStr;
}