目录
1.背景
使用hutool工具包中的httpUtil发送一个很常见的http post请求,
在单元测试的时候正常,但是整合到业务代码中报错:
cn.hutool.core.io.IORuntimeException: SSLException: Received fatal alert: internal_error
执行的核心代码:
/**
* 方法:执行同步
*/
private String send(String jsonParam) {
// 公共参数
long timestamp = System.currentTimeMillis() / 1000;
String sign = createSign(timestamp, appId, appSecret);
String url = host + "/download_center/push?appid=" + appId + "×tamp=" + timestamp + "&sign=" + sign;
HttpRequest request = HttpUtil.createPost(url);
request.setConnectionTimeout(5 * 1000);
request.setReadTimeout(30 * 1000);
request.body(jsonParam);
log.info("请求url:{}", url);
log.info("请求参数:{}", jsonParam);
String body = request.execute().body();
log.info("请求响应:{}", body);
return body;
}
报错截图如下:
这个问题之前遇到过,大致原因是;ssl/tsl协议版本不一致导致的;
但是这次最主要的不同是单元测试可以,业务代码中就不行,查看了使用的jdk版本等信息,
都是一样的
.......
在网上找了很久的解决方案,有的说更换jdk版本到1.8,可我的已经是1.8了...
最后,算了..实在找不到具体的原因,我就没有使用hutool同的http工具类,
而是自己封装了一个基于apache的http client,问题得到了解决
一直都很喜欢使用hutool的工具包,这次有点认人失望,或许是自己的技术不到位,还不能很好的使用吧!
2.解决方案
自己封装了一个基于apache的http client
执行的核心代码:
/**
* 方法:执行同步
*/
private String send2(String jsonParam) {
// 公共参数
long timestamp = System.currentTimeMillis() / 1000;
String sign = createSign(timestamp, appId, appSecret);
String url = host + "/download_center/push?appid=" + appId + "×tamp=" + timestamp + "&sign=" + sign;
log.info("请求url:{}", url);
log.info("请求参数:{}", jsonParam);
String body = null;
try {
body = HttpClientUtil.postJSON(url, jsonParam);
} catch (Exception e) {
log.error("http请求下载中心异常:", e);
}
log.info("请求响应:{}", body);
return body;
}
封装的http工具类:
import com.google.common.base.Charsets;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
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.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
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.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.CollectionUtils;
import javax.net.ssl.SSLContext;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.util.List;
import java.util.Map;
/**
* @Copyright (C) XXXX科技有限公司
* @Author: LI DONG PING
* @Date: 2019/4/11 17:51
* @Description:
*/
@Slf4j
public class HttpClientUtil {
private static final Logger logger = LoggerFactory.getLogger(HttpClientUtil.class);
// 发送GET请求
public static String getRequest(String path, List<NameValuePair> parametersBody) throws Exception {
URIBuilder uriBuilder = new URIBuilder(path);
uriBuilder.setParameters(parametersBody);
HttpGet get = new HttpGet(uriBuilder.build());
HttpClient client = HttpClientBuilder.create().build();
try {
HttpResponse response = client.execute(get);
int code = response.getStatusLine().getStatusCode();
if (code >= 400)
throw new RuntimeException((new StringBuilder()).append("Could not access protected resource. Server returned http code: ").append(code).toString());
return EntityUtils.toString(response.getEntity());
} catch (ClientProtocolException e) {
log.error("异常:", e);
} finally {
get.releaseConnection();
}
return null;
}
// 发送GET请求 带请求头
public static String getRequest(String path, List<NameValuePair> parametersBody, Map<String, String> map) throws Exception {
URIBuilder uriBuilder = new URIBuilder(path);
uriBuilder.setParameters(parametersBody);
HttpGet get = new HttpGet(uriBuilder.build());
if (!CollectionUtils.isEmpty(map)) {
for (Map.Entry<String, String> entry : map.entrySet())
get.addHeader(entry.getKey(), entry.getValue());
}
HttpClient client = HttpClientBuilder.create().build();
try {
HttpResponse response = client.execute(get);
int code = response.getStatusLine().getStatusCode();
if (code >= 400)
throw new RuntimeException((new StringBuilder()).append("Could not access protected resource. Server returned http code: ").append(code).toString());
return EntityUtils.toString(response.getEntity());
} catch (ClientProtocolException e) {
log.error("异常:", e);
} finally {
get.releaseConnection();
}
return null;
}
// 发送POST请求(普通表单形式)
public static String postForm(String path, List<NameValuePair> parametersBody) throws Exception {
HttpEntity entity = new UrlEncodedFormEntity(parametersBody, Charsets.UTF_8);
return postRequest(path, "application/x-www-form-urlencoded", entity);
}
// 发送POST请求(JSON形式)
public static String postJSON(String path, String json) throws Exception {
StringEntity entity = new StringEntity(json, Charsets.UTF_8);
entity.setContentType("application/json");
return postRequest(path, "application/json", entity);
}
// 发送POST请求
public static String postRequest(String path, String mediaType, HttpEntity entity) throws Exception {
logger.debug("[postRequest] resourceUrl: {}", path);
HttpPost post = new HttpPost(path);
RequestConfig requestConfig = RequestConfig.custom()
.setConnectTimeout(10000).setConnectionRequestTimeout(10000)
.setSocketTimeout(10000).build();
post.setConfig(requestConfig);
post.addHeader("Content-Type", mediaType);
post.addHeader("Accept", "application/json");
post.setEntity(entity);
try {
HttpClient client = HttpClientBuilder.create().setConnectionManager(createIgnoreVerifySSL()).build();
HttpResponse response = client.execute(post);
String s = EntityUtils.toString(response.getEntity());
logger.info("HTTP请求返回结果:" + s);
return s;
} catch (Exception e) {
logger.error("HTTP请求返回错误信息:" + e);
log.error("异常:", e);
} finally {
post.releaseConnection();
}
return null;
}
public static String doPost(String url, List<NameValuePair> list, String format) throws Exception {
logger.info("url=" + url + ",param=" + format);
// 获取默认的请求客户端
CloseableHttpClient client = HttpClients.createDefault();
// 通过HttpPost来发送post请求
HttpPost httpPost = new HttpPost(url);
UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(list);
httpPost.setEntity(formEntity);
CloseableHttpResponse response = client.execute(httpPost);
HttpEntity entity = response.getEntity();
String str = EntityUtils.toString(entity, "UTF-8");
// 关闭
response.close();
logger.info("请求发送完成,返回结果str=" + str);
return str;
}
public static String doPost(String url, List<NameValuePair> list) throws Exception {
// 获取默认的请求客户端
CloseableHttpClient client = HttpClients.createDefault();
// 通过HttpPost来发送post请求
HttpPost httpPost = new HttpPost(url);
httpPost.setHeader("Content-Type", "application/json;charset=UTF-8");
UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(list);
httpPost.setEntity(formEntity);
CloseableHttpResponse response = client.execute(httpPost);
HttpEntity entity = response.getEntity();
String str = EntityUtils.toString(entity, "UTF-8");
// 关闭
response.close();
logger.info("请求发送完成,返回结果str=" + str);
return str;
}
private static PoolingHttpClientConnectionManager createIgnoreVerifySSL() {
try {
SSLContext sslcontext = SslContext.createIgnoreVerifySSL();
Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
.register("http", PlainConnectionSocketFactory.INSTANCE)
.register("https", new SSLConnectionSocketFactory(sslcontext))
.build();
PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
return connManager;
} catch (NoSuchAlgorithmException e) {
log.error("异常:", e);
} catch (KeyManagementException e) {
log.error("异常:", e);
}
return null;
}
}