有时候调用外部https接口的时候会报证书错误
异常信息:javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target。
此时增加信任SSL证书即可,代码如下:
private static CloseableHttpClient httpClient;
//信任SSL证书
static {
try {
SSLContext sslContext = SSLContextBuilder.create().useProtocol(SSLConnectionSocketFactory.SSL).loadTrustMaterial((x, y) -> true).build();
RequestConfig config = RequestConfig.custom().setConnectTimeout(5000).setSocketTimeout(5000).build();
httpClient = HttpClientBuilder.create().setDefaultRequestConfig(config).setSSLContext(sslContext).setSSLHostnameVerifier((x, y) -> true).build();
} catch (Exception e) {
e.printStackTrace();
}
}
使用此httpClient发送请求即可。
附带完整工具类(带缓存与post)
package com.sky.common.utils;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.ssl.SSLContextBuilder;
import org.apache.http.util.EntityUtils;
import javax.net.ssl.SSLContext;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* irs api
*
* @author tommas灬wade
* @date 2022/6/16 10:29
*/
@Slf4j
public class PublicDataShareUtil {
private static RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(15000).setConnectTimeout(15000).setConnectionRequestTimeout(15000).build();
/**
* 预缓存信息
*/
private static final Map<String, Object> CACHE_MAP = new ConcurrentHashMap<>();
private static CloseableHttpClient httpClient;
//信任SSL证书
static {
try {
SSLContext sslContext = SSLContextBuilder.create().useProtocol(SSLConnectionSocketFactory.SSL).loadTrustMaterial((x, y) -> true).build();
RequestConfig config = RequestConfig.custom().setConnectTimeout(5000).setSocketTimeout(5000).build();
httpClient = HttpClientBuilder.create().setDefaultRequestConfig(config).setSSLContext(sslContext).setSSLHostnameVerifier((x, y) -> true).build();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 存放一个缓存对象,保存时间为holdTime
*
* @param cacheName cacheName
* @param obj obj
* @param holdTime holdTime
*/
public static void put(String cacheName, Object obj, long holdTime) {
CACHE_MAP.put(cacheName, obj);
//缓存失效时间
CACHE_MAP.put(cacheName + "_HoldTime", System.currentTimeMillis() + holdTime);
}
/**
* 取出一个缓存对象
*
* @param cacheName cacheName
* @return Object
*/
public static Object get(String cacheName) {
if (checkCacheName(cacheName)) {
return CACHE_MAP.get(cacheName);
}
return null;
}
/**
* 删除某个缓存
*
* @param cacheName cacheName
*/
public static void remove(String cacheName) {
CACHE_MAP.remove(cacheName);
CACHE_MAP.remove(cacheName + "_HoldTime");
}
/**
* 检查缓存对象是否存在,
* 若不存在,则返回false
* 若存在,检查其是否已过有效期,如果已经过了则删除该缓存并返回false
* @param cacheName cacheName
* @return boolean
*/
public static boolean checkCacheName(String cacheName) {
Long cacheHoldTime = (Long) CACHE_MAP.get(cacheName + "_HoldTime");
if (cacheHoldTime == null || cacheHoldTime == 0L) {
return false;
}
if (cacheHoldTime < System.currentTimeMillis()) {
remove(cacheName);
return false;
}
return true;
}
/**
* 发送 post 请求
*
* @param url 请求地址
* @param jsonStr Form表单json字符串
* @return 请求结果
*/
public static String postJson(String url, String jsonStr) {
// 创建post请求方式实例
HttpPost httpPost = new HttpPost(url);
// 设置请求头 发送的是json数据格式
httpPost.setHeader("Content-type", "application/json;charset=utf-8");
httpPost.setHeader("Connection", "Close");
// 设置参数---设置消息实体 也就是携带的数据aa
StringEntity entity = new StringEntity(jsonStr, StandardCharsets.UTF_8);
// 设置编码格式
entity.setContentEncoding("UTF-8");
// 发送Json格式的数据请求
entity.setContentType("application/json");
// 把请求消息实体塞进去
httpPost.setEntity(entity);
// 执行http的post请求
CloseableHttpResponse httpResponse;
String result = null;
try {
httpResponse = httpClient.execute(httpPost);
result = EntityUtils.toString(httpResponse.getEntity(), "UTF-8");
} catch (IOException e) {
e.printStackTrace();
}
return result;
}
public static String postForm(String httpUrl, Map<String, String> maps, Map<String, String> header) {
HttpPost httpPost = new HttpPost(httpUrl);
List<NameValuePair> nameValuePairs = new ArrayList();
for (String key : maps.keySet()) {
nameValuePairs.add(new BasicNameValuePair(key, (String) maps.get(key)));
}
try {
httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs, "UTF-8"));
} catch (Exception var6) {
var6.printStackTrace();
}
return postHttp(httpPost);
}
private static String postHttp(HttpPost httpPost) {
CloseableHttpResponse response = null;
HttpEntity entity = null;
String responseContent = null;
try {
httpPost.setConfig(requestConfig);
response = httpClient.execute(httpPost);
entity = response.getEntity();
responseContent = EntityUtils.toString(entity, "UTF-8");
} catch (Exception var14) {
var14.printStackTrace();
} finally {
try {
if (response != null) {
response.close();
}
} catch (IOException var13) {
var13.printStackTrace();
}
}
return responseContent;
}
}