package com.cybertogether.wx.notice.infrastructure; import com.alibaba.fastjson.JSONObject; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.http.Consts; import org.apache.http.HttpEntity; import org.apache.http.HttpHeaders; 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.*; import org.apache.http.config.*; 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.ContentType; import org.apache.http.entity.StringEntity; import org.apache.http.entity.mime.HttpMultipartMode; import org.apache.http.entity.mime.MultipartEntityBuilder; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; import org.apache.http.message.BasicNameValuePair; import org.apache.http.ssl.SSLContexts; import org.apache.http.util.EntityUtils; import javax.net.ssl.SSLContext; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; import java.io.File; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.nio.charset.CodingErrorAction; import java.security.KeyManagementException; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import java.util.*; /** * @description: * @author: TanJingyu * @create:2023-06-14 14:11:21 **/ public class HttpClientUtils { static Log log = LogFactory.getLog(HttpClientUtils.class); private static CloseableHttpClient client; private static RequestConfig requestConfigDefault; private static PoolingHttpClientConnectionManager connManager = null; // 默认请求获取数据的超时时间 private static Integer readTimeoutDefault = 15000; // 默认连接超时时间 private static Integer connectTimeoutDefault = 5000; // 默认从connectManager获取Connection超时时间 private static Integer getConnectionTimeoutDefault = 1000; // 默认的字符集 private static String charsetDefault = "UTF-8"; public static final String contentTypeJson = "application/json"; public static final String contentTypeXml = "application/xml"; private enum MethodType { GET, POST } static { try { SSLContext sslContext = SSLContexts.createDefault(); sslContext.init(null, new TrustManager[]{new X509TrustManager() { public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException { } public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException { } public X509Certificate[] getAcceptedIssuers() { return null; } }}, null); Registry socketFactoryRegistry = RegistryBuilder.create() .register("http", PlainConnectionSocketFactory.INSTANCE) .register("https", new SSLConnectionSocketFactory(sslContext)).build(); connManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry); SocketConfig socketConfig = SocketConfig.custom().setTcpNoDelay(true).build(); connManager.setDefaultSocketConfig(socketConfig); MessageConstraints messageConstraints = MessageConstraints.custom().build(); ConnectionConfig connectionConfig = ConnectionConfig.custom() .setMalformedInputAction(CodingErrorAction.IGNORE) .setUnmappableInputAction(CodingErrorAction.IGNORE).setCharset(Consts.UTF_8) .setMessageConstraints(messageConstraints).build(); connManager.setDefaultConnectionConfig(connectionConfig); connManager.setMaxTotal(1000); connManager.setDefaultMaxPerRoute(500); connManager.setValidateAfterInactivity(3000); } catch (KeyManagementException e) { log.error(e); } requestConfigDefault = RequestConfig.custom().setConnectionRequestTimeout(getConnectionTimeoutDefault) .setConnectTimeout(connectTimeoutDefault).setSocketTimeout(readTimeoutDefault).build(); client = HttpClients.custom().useSystemProperties().setConnectionManager(connManager).setDefaultRequestConfig(requestConfigDefault) .build(); } /** * get请求 * * @param url 请求的url * @return HttpResponseContent对象,如果http请求出现异常,返回null */ public static HttpResponseContent get(String url) { return get(url, null, connectTimeoutDefault, readTimeoutDefault, null); } /** * @param url 请求的url * @param headers 请求需要携带的header信息 * @return HttpResponseContent对象,如果http请求出现异常,返回null */ public static HttpResponseContent get(String url, Map headers) { return get(url, null, connectTimeoutDefault, readTimeoutDefault, headers); } /** * get请求 * * @param url 请求的url * @param contentType contentType,例如:text/plain * @return HttpResponseContent对象,如果http请求出现异常,返回null */ public static HttpResponseContent get(String url, String contentType) { return get(url, contentType, connectTimeoutDefault, readTimeoutDefault, null); } /** * get请求 * * @param url 请求的url * @param connectTimeout 连接超时设置,毫秒 * @param readTimeout 读取超时设置,毫秒 * @return HttpResponseContent对象,如果http请求出现异常,返回null */ public static HttpResponseContent get(String url, int connectTimeout, int readTimeout) { return get(url, null, connectTimeout, readTimeout, null); } /** * get请求 * * @param url 请求的url * @param contentType contentType,例如:text/plain * @param connectTimeout 连接超时设置,毫秒 * @param readTimeout 读取超时设置,毫秒 * @param headers 请求需要携带的header信息 * @return HttpResponseContent对象,如果http请求出现异常,返回null */ public static HttpResponseContent get(String url, String contentType, int connectTimeout, int readTimeout, Map headers) { return getOrPostUrl(MethodType.GET, url, contentType, connectTimeout, readTimeout, headers); } /** * post请求,参数在url中 * * @param url 请求的url * @return HttpResponseContent对象,如果http请求出现异常,返回null */ public static HttpResponseContent postUrl(String url) { return postUrl(url, null, connectTimeoutDefault, readTimeoutDefault); } /** * post请求,参数在url中 * * @param url 请求的url * @param contentType contentType,例如:text/plain * @return HttpResponseContent对象,如果http请求出现异常,返回null */ public static HttpResponseContent postUrl(String url, String contentType) { return postUrl(url, contentType, connectTimeoutDefault, readTimeoutDefault); } /** * post请求,参数在url中 * * @param url 请求的url * @param connectTimeout 连接超时设置,毫秒 * @param readTimeout 读取超时设置,毫秒 * @return HttpResponseContent对象,如果http请求出现异常,返回null */ public static HttpResponseContent postUrl(String url, int connectTimeout, int readTimeout) { return postUrl(url, null, connectTimeout, readTimeout); } /** * post请求,参数在url中 * * @param url 请求的url * @param contentType contentType,例如:text/plain * @param connectTimeout 连接超时设置,毫秒 * @param readTimeout 读取超时设置,毫秒 * @return HttpResponseContent对象,如果http请求出现异常,返回null */ public static HttpResponseContent postUrl(String url, String contentType, int connectTimeout, int readTimeout) { return getOrPostUrl(MethodType.POST, url, contentType, connectTimeout, readTimeout); } /** * get或者post请求,参数在url中 * * @param methodType GET/POST * @param url 请求的url * @param contentType contentType,例如:text/plain * @param connectTimeout 连接超时设置,毫秒 * @param readTimeout 读取超时设置,毫秒 * @return HttpResponseContent对象,如果http请求出现异常,返回null */ private static HttpResponseContent getOrPostUrl(MethodType methodType, String url, String contentType, int connectTimeout, int readTimeout) { return getOrPostUrl(methodType, url, contentType, connectTimeout, readTimeout, null); } private static HttpResponseContent getOrPostUrl(MethodType methodType, String url, String contentType, int connectTimeout, int readTimeout, Map extHeaders) { HttpRequestBase request = null; HttpResponseContent hrc = null; if (methodType == MethodType.GET) { request = new HttpGet(url); } else { request = new HttpPost(url); } // 设置contentType if (contentType != null) { request.addHeader(HttpHeaders.CONTENT_TYPE, contentType); } //add by nieqi since 2022-3-23 if (Objects.nonNull(extHeaders)) { for (String s : extHeaders.keySet()) { if (Objects.nonNull(s)) { String headerValue = extHeaders.get(s); if (Objects.nonNull(headerValue)) { request.addHeader(s, headerValue); } } } } hrc = executeHttpRequest(request, connectTimeout, readTimeout); return hrc; } /** * post请求,请求数据在data中 * * @param url 请求的url * @param data 请求数据 * @return HttpResponseContent对象,如果http请求出现异常,返回null */ public static HttpResponseContent postData(String url, String data) { return postData(url, data, null, connectTimeoutDefault, readTimeoutDefault); } /** * post请求,请求数据在data中 * * @param url 请求的url * @param data 请求数据 * @param contentType contentType,例如:text/plain * @return HttpResponseContent对象,如果http请求出现异常,返回null */ public static HttpResponseContent postData(String url, String data, String contentType) { return postData(url, data, contentType, connectTimeoutDefault, readTimeoutDefault); } /** * post请求,请求数据在data中 * * @param url 请求的url * @param data 请求数据 * @param connectTimeout 连接超时设置,毫秒 * @param readTimeout 读取超时设置,毫秒 * @return HttpResponseContent对象,如果http请求出现异常,返回null */ public static HttpResponseContent postData(String url, String data, int connectTimeout, int readTimeout) { return postData(url, data, null, connectTimeout, readTimeout); } /** * post请求,请求数据在data中 * * @param url 请求的url * @param data 请求数据 * @param contentType contentType,例如:text/plain * @param connectTimeout 连接超时设置,毫秒 * @param readTimeout 读取超时设置,毫秒 * @return HttpResponseContent对象,如果http请求出现异常,返回null */ public static HttpResponseContent postData(String url, String data, String contentType, int connectTimeout, int readTimeout) { Map headerMap = new HashMap(); headerMap.put(HttpHeaders.CONTENT_TYPE, contentType); return postDataAddHeader(url, data, headerMap, connectTimeout, readTimeout); } /** * post请求,请求数据在data中 * * @param url 请求的url * @param data 请求数据 * @param headerMap http请求头,key-value放在map中 * @param connectTimeout 连接超时设置,毫秒 * @param readTimeout 读取超时设置,毫秒 * @return HttpResponseContent对象,如果http请求出现异常,返回null */ public static HttpResponseContent postDataAddHeader(String url, String data, Map headerMap, int connectTimeout, int readTimeout) { HttpRequestBase request = null; HttpResponseContent hrc = null; HttpPost httpPost = new HttpPost(url); httpPost.setEntity(new StringEntity(data, charsetDefault)); request = httpPost; // 设置header if (headerMap != null) { for (Map.Entry entry : headerMap.entrySet()) { request.addHeader(entry.getKey(), entry.getValue()); } } hrc = executeHttpRequest(request, connectTimeout, readTimeout); return hrc; } /** * post请求,form表单,不能包含二进制数据 * * @param url 请求的url * @param paramsMap form表单参数map * @param headerMap form表单header * @return HttpResponseContent对象,如果http请求出现异常,返回null */ public static HttpResponseContent postForm(String url, Map paramsMap, Map headerMap) { return postForm(url, paramsMap, connectTimeoutDefault, readTimeoutDefault, headerMap); } /** * post请求,form表单,不能包含二进制数据 * * @param url 请求的url * @param paramsMap form表单参数map * @param connectTimeout 连接超时设置,毫秒 * @param readTimeout 读取超时设置,毫秒 * @param headerMap form表单header * @return HttpResponseContent对象,如果http请求出现异常,返回null */ public static HttpResponseContent postForm(String url, Map paramsMap, int connectTimeout, int readTimeout, Map headerMap) { HttpRequestBase request = null; HttpResponseContent hrc = null; HttpPost httpPost = new HttpPost(url); List nvps = new ArrayList(); if (Objects.nonNull(paramsMap)) { Iterator iterator = paramsMap.keySet().iterator(); while (iterator.hasNext()) { String key = iterator.next(); Object value = paramsMap.get(key); nvps.add(new BasicNameValuePair(key, String.valueOf(value))); } } // 设置header if (headerMap != null) { for (Map.Entry entry : headerMap.entrySet()) { httpPost.addHeader(entry.getKey(), entry.getValue()); } } try { httpPost.setEntity(new UrlEncodedFormEntity(nvps, charsetDefault)); } catch (UnsupportedEncodingException e) { log.error(e); } request = httpPost; hrc = executeHttpRequest(request, connectTimeout, readTimeout); return hrc; } /** * post请求,multipart,支持File,byte[]这两种二进制数据 * * @param url 请求的url * @param paramsMap 请求参数map * @return HttpResponseContent对象,如果http请求出现异常,返回null */ public static HttpResponseContent postMultipart(String url, Map paramsMap) { return postMultipart(url, paramsMap, connectTimeoutDefault, readTimeoutDefault, null); } public static HttpResponseContent postMultipart(String url, Map paramsMap, Map headerMap) { return postMultipart(url, paramsMap, connectTimeoutDefault, readTimeoutDefault, headerMap); } /** * post请求,multipart,支持File,byte[]这两种二进制数据 * * @param url 请求的url * @param paramsMap 请求参数map * @param connectTimeout 连接超时设置,毫秒 * @param readTimeout 读取超时设置,毫秒 * @return HttpResponseContent对象,如果http请求出现异常,返回null */ public static HttpResponseContent postMultipart(String url, Map paramsMap, int connectTimeout, int readTimeout, Map headerMap) { HttpRequestBase request = null; HttpResponseContent hrc = null; HttpPost httpPost = new HttpPost(url); MultipartEntityBuilder multipartEntityBuilder = MultipartEntityBuilder.create(); multipartEntityBuilder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE); Iterator iterator = paramsMap.keySet().iterator(); while (iterator.hasNext()) { String key = iterator.next(); Object value = paramsMap.get(key); if (value instanceof File) { multipartEntityBuilder.addBinaryBody(key, (File) value); } else if (value instanceof byte[]) { multipartEntityBuilder.addBinaryBody(key, (byte[]) value); } else { multipartEntityBuilder.addTextBody(key, String.valueOf(value), ContentType.create("text/plain", charsetDefault)); } } httpPost.setEntity(multipartEntityBuilder.build()); // 设置header if (headerMap != null) { for (Map.Entry entry : headerMap.entrySet()) { httpPost.addHeader(entry.getKey(), entry.getValue()); } } request = httpPost; hrc = executeHttpRequest(request, connectTimeout, readTimeout); return hrc; } public static HttpResponseContent postRequestBody(String url, Object s, Map headerMap) { HttpRequestBase request = null; HttpResponseContent hrc = null; HttpPost httpPost = new HttpPost(url); StringEntity stringEntity = new StringEntity((s instanceof String) ? (String) s : JSONObject.toJSONString(s), Consts.UTF_8); stringEntity.setContentEncoding(Consts.UTF_8.name()); stringEntity.setContentType("application/json"); httpPost.setEntity(stringEntity); // 设置header if (headerMap != null) { for (Map.Entry entry : headerMap.entrySet()) { httpPost.addHeader(entry.getKey(), entry.getValue()); } } request = httpPost; hrc = executeHttpRequest(request, connectTimeoutDefault, readTimeoutDefault); return hrc; } public static HttpResponseContent deleteRequestBody(String url, Object s, HashMap headerMap) { HttpRequestBase request = null; HttpResponseContent hrc = null; HttpDeleteExpand httpDelete = new HttpDeleteExpand(url); StringEntity stringEntity = new StringEntity(JSONObject.toJSONString(s), Consts.UTF_8); stringEntity.setContentEncoding(Consts.UTF_8.name()); stringEntity.setContentType("application/json"); httpDelete.setEntity(stringEntity); // 设置header if (headerMap != null) { for (Map.Entry entry : headerMap.entrySet()) { httpDelete.addHeader(entry.getKey(), entry.getValue()); } } request = httpDelete; hrc = executeHttpRequest(request, connectTimeoutDefault, readTimeoutDefault); return hrc; } public static HttpResponseContent putRequestBody(String url, Object s, HashMap headerMap) { HttpRequestBase request = null; HttpResponseContent hrc = null; HttpPut httpPut = new HttpPut(url); StringEntity stringEntity = new StringEntity(JSONObject.toJSONString(s), Consts.UTF_8); stringEntity.setContentEncoding(Consts.UTF_8.name()); stringEntity.setContentType("application/json"); httpPut.setEntity(stringEntity); // 设置header if (headerMap != null) { for (Map.Entry entry : headerMap.entrySet()) { httpPut.addHeader(entry.getKey(), entry.getValue()); } } request = httpPut; hrc = executeHttpRequest(request, connectTimeoutDefault, readTimeoutDefault); return hrc; } /** * 执行Http请求 * * @param request * @param connectTimeout * @param readTimeout * @return HttpResponseContent对象,如果http请求出现异常,返回null */ private static HttpResponseContent executeHttpRequest(HttpRequestBase request, int connectTimeout, int readTimeout) { CloseableHttpResponse response = null; HttpResponseContent hrc = null; try { // 设置请求配置 RequestConfig.Builder configBuilder = RequestConfig.custom(); // 设置连接超时 configBuilder.setConnectTimeout(connectTimeout); // 设置读取超时 configBuilder.setSocketTimeout(readTimeout); // 设置从连接池获取连接实例的超时 configBuilder.setConnectionRequestTimeout(getConnectionTimeoutDefault); RequestConfig requestConfig = configBuilder.build(); request.setConfig(requestConfig); log.debug("开始执行Http请求, uri:" + request.getURI()); response = client.execute(request); hrc = getHttpResponseContent(response); return hrc; } catch (Exception e) { log.error("执行Http请求异常, uri:" + request.getURI(), e); } finally { close(request, response); } return hrc; } /** * 封装HTTP响应报文 * * @param response * @return */ private static HttpResponseContent getHttpResponseContent(CloseableHttpResponse response) { // 获取响应实体 HttpEntity entity = response.getEntity(); if (entity == null) { return null; } HttpResponseContent hrc = new HttpResponseContent(); hrc.setHeaders(response.getAllHeaders()); hrc.setStatusCode(response.getStatusLine().getStatusCode()); ContentType contentType = ContentType.getOrDefault(entity); hrc.setMimeType(contentType.getMimeType()); if (contentType.getCharset() != null) { hrc.setCharsetName(contentType.getCharset().name()); } try { hrc.setContentBytes(EntityUtils.toByteArray(entity)); } catch (IOException e) { log.error("封装HTTP响应报文异常", e); } return hrc; } /** * 关闭资源 * * @param request * @param response */ private static void close(HttpRequestBase request, CloseableHttpResponse response) { try { if (request != null) request.releaseConnection(); if (response != null) response.close(); } catch (Exception e) { log.error("关闭资源异常", e); } } /** * url编码 * * @param url * @param charset * @return */ public static String encodeURL(String url, String charset) { if (url == null || charset == null) { return null; } int p = url.indexOf("?"); if (p < 0) { return url; } StringBuilder sb = new StringBuilder(); String preStr = url.substring(0, p + 1); sb.append(preStr); String queryStr = url.substring(p + 1, url.length()); String[] array = queryStr.split("&"); for (int i = 0; i < array.length; i++) { String str = array[i]; int pp = str.indexOf("="); if (pp > -1) { sb.append(str.substring(0, pp + 1)); try { sb.append(URLEncoder.encode(str.substring(pp + 1, str.length()), charset)); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } if (i < array.length - 1) { sb.append("&"); } } } return sb.toString(); } }