第一种写法:
import java.io.IOException; import java.io.InterruptedIOException; import java.io.UnsupportedEncodingException; import java.net.SocketTimeoutException; import java.net.URLEncoder; import java.net.UnknownHostException; import java.nio.charset.Charset; import java.security.KeyManagementException; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.List; import java.util.Map; import javax.activation.MimetypesFileTypeMap; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLException; import org.apache.commons.lang3.StringUtils; import org.apache.http.Header; import org.apache.http.HttpEntity; import org.apache.http.HttpEntityEnclosingRequest; import org.apache.http.HttpHost; import org.apache.http.HttpRequest; import org.apache.http.NameValuePair; import org.apache.http.ParseException; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.HttpRequestRetryHandler; import org.apache.http.client.config.RequestConfig; import org.apache.http.client.config.RequestConfig.Builder; 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.protocol.HttpClientContext; import org.apache.http.conn.ConnectTimeoutException; import org.apache.http.conn.ssl.SSLConnectionSocketFactory; import org.apache.http.conn.ssl.TrustStrategy; import org.apache.http.entity.ContentType; 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.message.BasicNameValuePair; import org.apache.http.protocol.HTTP; import org.apache.http.protocol.HttpContext; import org.apache.http.ssl.SSLContextBuilder; import org.apache.http.util.EntityUtils; import lombok.extern.slf4j.Slf4j; import net.dreamlu.common.entity.DownLoadFile; import net.sf.json.JSONObject; import net.sf.json.JsonConfig; import net.sf.json.util.PropertyFilter; @Slf4j public class HttpclientUtils implements IDictConst { private final static int CONNECT_TIMEOUT = 4000; // 连接超时毫秒 private final static int SOCKET_TIMEOUT = 30000; // 传输超时毫秒 private final static int REQUESTCONNECT_TIMEOUT = 3000; // 获取请求超时毫秒 private final static String ENCODE_CHARSET = "utf-8"; // 响应报文解码字符集 static class RetryHandler implements HttpRequestRetryHandler { @Override public boolean retryRequest(IOException exception, int executionCount, HttpContext context) { if (executionCount >= 3) { // Do not retry if over max retry count return false; } if (exception instanceof InterruptedIOException) { // Timeout return false; } if (exception instanceof UnknownHostException) { // Unknown host return false; } if (exception instanceof ConnectTimeoutException) { // Connection refused return false; } if (exception instanceof SSLException) { // SSL handshake exception return false; } HttpClientContext clientContext = HttpClientContext.adapt(context); HttpRequest request = clientContext.getRequest(); boolean idempotent = !(request instanceof HttpEntityEnclosingRequest); if (idempotent) { // Retry if the request is considered idempotent return true; } return false; } }; public static CloseableHttpClient createSSLClientDefault(HttpHost proxy) { try { SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() { // 信任所有 @Override public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException { return true; } }).build(); SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext); HttpRequestRetryHandler retryHandler = new RetryHandler(); Builder buider = RequestConfig.custom().setConnectionRequestTimeout(REQUESTCONNECT_TIMEOUT).setConnectTimeout(CONNECT_TIMEOUT).setSocketTimeout(SOCKET_TIMEOUT); if (null != proxy) { buider.setProxy(proxy); } RequestConfig requestConfig = buider.build(); HttpClients.custom().setSSLSocketFactory(sslsf).setDefaultRequestConfig(requestConfig).setRetryHandler(retryHandler).build(); } catch (KeyManagementException | NoSuchAlgorithmException | KeyStoreException e) { log.error(e.getMessage(), e); } return HttpClients.createDefault(); } public static String buildMap(Map<String, Object> map) { StringBuffer sb = new StringBuffer(); if (map != null && map.size() > 0) { for (String key : map.keySet()) { sb.append(key + "="); if (null == map.get(key)) { sb.append("&"); } else { String value = String.valueOf(map.get(key)); try { value = URLEncoder.encode(value, "UTF-8"); } catch (UnsupportedEncodingException e) { log.error(e.getMessage(), e); } sb.append(value + "&"); } } } return sb.toString(); } /** * 发送HTTP_GET请求 * * @see 1)该方法会自动关闭连接,释放资源 * @see 2)方法内设置了连接和读取超时时间,单位为毫秒,超时或发生其它异常时方法会自动返回"通信失败"字符串 * @see 3)请求参数含中文时,经测试可直接传入中文,HttpClient会自动编码发给Server,应用时应根据实际效果决 定传入前是否转码 * @see 4)该方法会自动获取到响应消息头中[Content-Type:text/html; charset=GBK]的charset值作为响应报文的 解码字符集 * @see 5)若响应消息头中无Content-Type属性,则会使用HttpClient内部默认的ISO-8859-1作为响应报文的解码字符 集 * @param reqURL 请求地址(含参数) * @return 远程主机响应正文 HttpHost proxy = new HttpHost("192.168.15.4", 3128); */ public static JSONObject sendGetRequest(String reqURL, Map<String, Object> map, HttpHost proxy) { String param = buildMap(map); if (null != param) { reqURL += "?" + param; } JSONObject respContent = new JSONObject(); // 响应内容 // reqURL = URLDecoder.decode(reqURL, ENCODE_CHARSET); HttpGet httpget = new HttpGet(reqURL); httpget.setHeader("Connection", "close"); CloseableHttpResponse response = null; try { response = createSSLClientDefault(proxy).execute(httpget, HttpClientContext.create()); // 执行GET请求 HttpEntity entity = response.getEntity(); // 获取响应实体 if (null != entity) { Charset respCharset = Charset.forName(ENCODE_CHARSET); respContent = JSONObject.fromObject(EntityUtils.toString(entity, respCharset), getJsonConfig()); log.info("发送get请求返回结果:{}", respContent); EntityUtils.consume(entity); } else { log.error("发送get请求返回错误:{}", response); } } catch (ConnectTimeoutException cte) { log.error("请求通信[" + reqURL + "]时连接超时,堆栈轨迹如下", cte); respContent.put(CODE, -1000); respContent.put(MSG, cte.getMessage()); } catch (SocketTimeoutException ste) { log.error("请求通信[" + reqURL + "]时读取超时,堆栈轨迹如下", ste); respContent.put(CODE, -1000); respContent.put(MSG, ste.getMessage()); } catch (ClientProtocolException cpe) { log.error("请求通信[" + reqURL + "]时协议异常,堆栈轨迹如下", cpe); respContent.put(CODE, -1000); respContent.put(MSG, cpe.getMessage()); } catch (ParseException pe) { log.error("请求通信[" + reqURL + "]时解析异常,堆栈轨迹如下", pe); respContent.put(CODE, -1000); respContent.put(MSG, pe.getMessage()); } catch (IOException ioe) { log.error("请求通信[" + reqURL + "]时网络异常,堆栈轨迹如下", ioe); respContent.put(CODE, -1000); respContent.put(MSG, ioe.getMessage()); } catch (Exception e) { log.error("请求通信[" + reqURL + "]时偶遇异常,堆栈轨迹如下", e); respContent.put(CODE, -1000); respContent.put(MSG, e.getMessage()); } finally { try { if (response != null) response.close(); } catch (IOException e) { e.printStackTrace(); } if (httpget != null) { httpget.releaseConnection(); } } return respContent; } /** * 将null值的字段去掉 * * @return */ private static JsonConfig getJsonConfig() { JsonConfig jsonConfig = new JsonConfig(); jsonConfig.setJsonPropertyFilter(new PropertyFilter() { @Override public boolean apply(Object arg0, String arg1, Object arg2) { return StringUtils.equals("null", String.valueOf(arg2)); } }); return jsonConfig; } /** * 发送HTTP_POST请求 type: 默认是表单请求, * * @see 1)该方法允许自定义任何格式和内容的HTTP请求报文体 * @see 2)该方法会自动关闭连接,释放资源 * @see 3)方法内设置了连接和读取超时时间,单位为毫秒,超时或发生其它异常时方法会自动返回"通信失败"字符串 * @see 4)请求参数含中文等特殊字符时,可直接传入本方法,并指明其编码字符集encodeCharset参数,方法内部会自 动对其转码 * @see 5)该方法在解码响应报文时所采用的编码,取自响应消息头中的[Content-Type:text/html; charset=GBK]的 charset值 * @see 6)若响应消息头中未指定Content-Type属性,则会使用HttpClient内部默认的ISO-8859-1 * @param reqURL 请求地址 * @param param 请求参数,若有多个参数则应拼接为param11=value11&22=value22&33=value33的形式 * @param type 编码字符集,编码请求数据时用之,此参数为必填项(不能为""或null) * @return 远程主机响应正文 */ public static JSONObject sendPostRequest(String reqURL, Map<String, Object> map, String type, HttpHost proxy) { JSONObject respContent = new JSONObject(); // 设置请求和传输超时时间 HttpPost httpPost = new HttpPost(reqURL); httpPost.setHeader("Connection", "close"); // 这就有可能会导致服务端接收不到POST过去的参数,比如运行在Tomcat6.0.36中的Servlet,所以我们手工指定CONTENT_TYPE头消息 if (type != null && type.length() > 0) { httpPost.setHeader(HTTP.CONTENT_TYPE, "application/json; charset=" + ENCODE_CHARSET); } else { httpPost.setHeader(HTTP.CONTENT_TYPE, "application/x-www-form-urlencoded; charset=" + ENCODE_CHARSET); } CloseableHttpResponse response = null; try { // 判断map不为空 if (map != null) { // 声明存放参数的List集合 List<NameValuePair> params = new ArrayList<NameValuePair>(); // 遍历map,设置参数到list中 for (Map.Entry<String, Object> entry : map.entrySet()) { if (null != entry.getValue()) { params.add(new BasicNameValuePair(entry.getKey(), String.valueOf(entry.getValue()))); } } // 创建form表单对象 UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(params, ENCODE_CHARSET); formEntity.setContentType("Content-Type:application/json"); // 把表单对象设置到httpPost中 httpPost.setEntity(formEntity); } // reqURL = URLDecoder.decode(reqURL, ENCODE_CHARSET); response = createSSLClientDefault(proxy).execute(httpPost, HttpClientContext.create()); HttpEntity entity = response.getEntity(); if (null != entity) { respContent = JSONObject.fromObject(EntityUtils.toString(entity, Charset.forName(ENCODE_CHARSET)), getJsonConfig()); log.info("发送post请求返回结果:{}", respContent); EntityUtils.consume(entity); } else { log.error("发送post请求返回错误:{}", response); } } catch (ConnectTimeoutException cte) { log.error("请求通信[" + reqURL + "]时连接超时,堆栈轨迹如下", cte); respContent.put(CODE, -1000); respContent.put(MSG, cte.getMessage()); } catch (SocketTimeoutException ste) { log.error("请求通信[" + reqURL + "]时读取超时,堆栈轨迹如下", ste); respContent.put(CODE, -1000); respContent.put(MSG, ste.getMessage()); } catch (ClientProtocolException cpe) { log.error("请求通信[" + reqURL + "]时协议异常,堆栈轨迹如下", cpe); respContent.put(CODE, -1000); respContent.put(MSG, cpe.getMessage()); } catch (ParseException pe) { log.error("请求通信[" + reqURL + "]时解析异常,堆栈轨迹如下", pe); respContent.put(CODE, -1000); respContent.put(MSG, pe.getMessage()); } catch (IOException ioe) { log.error("请求通信[" + reqURL + "]时网络异常,堆栈轨迹如下", ioe); respContent.put(CODE, -1000); respContent.put(MSG, ioe.getMessage()); } catch (Exception e) { log.error("请求通信[" + reqURL + "]时偶遇异常,堆栈轨迹如下", e); respContent.put(CODE, -1000); respContent.put(MSG, e.getMessage()); } finally { try { if (response != null) response.close(); } catch (IOException e) { e.printStackTrace(); } if (httpPost != null) { httpPost.releaseConnection(); } } return respContent; } public static String getContentType(String filename) { String contentType = null; try { contentType = new MimetypesFileTypeMap().getContentType(filename); } catch (Exception e) { e.printStackTrace(); } return contentType; } /** * 上传文件功能 * * @param reqURL * @param b * @param filename * @param map * @param type * @return */ public static JSONObject sendPostFileRequest(String reqURL, byte[] b, String filename, Map<String, Object> map, HttpHost proxy) { JSONObject respContent = new JSONObject(); HttpPost httpPost = new HttpPost(reqURL); httpPost.setHeader("Connection", "close"); CloseableHttpResponse response = null; try { // 判断map不为空 if (map != null) { MultipartEntityBuilder multipartEntityBuilder = MultipartEntityBuilder.create(); multipartEntityBuilder.setCharset(Charset.forName(ENCODE_CHARSET)); multipartEntityBuilder.addBinaryBody("file", b, ContentType.create(getContentType(filename)), filename); for (Map.Entry<String, Object> entry : map.entrySet()) { multipartEntityBuilder.addTextBody(entry.getKey(), String.valueOf(entry.getValue())); } HttpEntity httpEntity = multipartEntityBuilder.build(); httpPost.setEntity(httpEntity); } // reqURL = URLDecoder.decode(reqURL, ENCODE_CHARSET); response = createSSLClientDefault(proxy).execute(httpPost, HttpClientContext.create()); HttpEntity entity = response.getEntity(); if (null != entity) { respContent = JSONObject.fromObject(EntityUtils.toString(entity, Charset.forName(ENCODE_CHARSET)), getJsonConfig()); log.info("发送post请求返回结果:{}", respContent); EntityUtils.consume(entity); } else { log.error("发送post请求返回错误:{}", response); } } catch (ConnectTimeoutException cte) { log.error("请求通信[" + reqURL + "]时连接超时,堆栈轨迹如下", cte); respContent.put(CODE, -1000); respContent.put(MSG, cte.getMessage()); } catch (SocketTimeoutException ste) { log.error("请求通信[" + reqURL + "]时读取超时,堆栈轨迹如下", ste); respContent.put(CODE, -1000); respContent.put(MSG, ste.getMessage()); } catch (ClientProtocolException cpe) { log.error("请求通信[" + reqURL + "]时协议异常,堆栈轨迹如下", cpe); respContent.put(CODE, -1000); respContent.put(MSG, cpe.getMessage()); } catch (ParseException pe) { log.error("请求通信[" + reqURL + "]时解析异常,堆栈轨迹如下", pe); respContent.put(CODE, -1000); respContent.put(MSG, pe.getMessage()); } catch (IOException ioe) { log.error("请求通信[" + reqURL + "]时网络异常,堆栈轨迹如下", ioe); respContent.put(CODE, -1000); respContent.put(MSG, ioe.getMessage()); } catch (Exception e) { log.error("请求通信[" + reqURL + "]时偶遇异常,堆栈轨迹如下", e); respContent.put(CODE, -1000); respContent.put(MSG, e.getMessage()); } finally { try { if (response != null) response.close(); } catch (IOException e) { e.printStackTrace(); } if (httpPost != null) { httpPost.releaseConnection(); } } return respContent; } /** * 上传文件功能 * * @param reqURL * @param b * @param filename * @param map * @param type * @return */ public static DownLoadFile downFileRequest(String reqURL, Map<String, Object> map, HttpHost proxy) { DownLoadFile respContent = new DownLoadFile(); HttpPost httpPost = new HttpPost(reqURL); httpPost.setHeader("Connection", "close"); CloseableHttpResponse response = null; try { // 判断map不为空 if (map != null) { // 声明存放参数的List集合 List<NameValuePair> params = new ArrayList<NameValuePair>(); // 遍历map,设置参数到list中 for (Map.Entry<String, Object> entry : map.entrySet()) { if (null != entry.getValue()) { params.add(new BasicNameValuePair(entry.getKey(), String.valueOf(entry.getValue()))); } } // 创建form表单对象 UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(params, ENCODE_CHARSET); formEntity.setContentType("Content-Type:application/json"); // 把表单对象设置到httpPost中 httpPost.setEntity(formEntity); } // reqURL = URLDecoder.decode(reqURL, ENCODE_CHARSET); response = createSSLClientDefault(proxy).execute(httpPost, HttpClientContext.create()); int code = response.getStatusLine().getStatusCode(); if (code == 302) { Header header = response.getFirstHeader("location"); // 跳转的目标地址是在 HTTP-HEAD上 String newuri = header.getValue(); // 这就是跳转后的地址,再向这个地址发出新申请 httpPost = new HttpPost(newuri); httpPost.setHeader("Content-Type", "application/x-www-form-urlencoded"); response = createSSLClientDefault(proxy).execute(httpPost, HttpClientContext.create()); code = response.getStatusLine().getStatusCode(); if (code == 200) { respContent.setFileName(StringUtils.substringAfterLast(newuri, "/")); HttpEntity entity = response.getEntity(); if (null != entity) { respContent.setFileContent(EntityUtils.toByteArray(entity)); EntityUtils.consume(entity); } else { log.error("发送post请求返回错误:{}", response); } } } else if (code == 200) { Header header = response.getFirstHeader("location"); // 跳转的目标地址是在 HTTP-HEAD上 String newuri = header.getValue(); HttpEntity entity = response.getEntity(); if (null != entity) { respContent.setFileName(StringUtils.substringAfterLast(newuri, "/")); respContent.setFileContent(EntityUtils.toByteArray(entity)); EntityUtils.consume(entity); } else { log.error("发送post请求返回错误:{}", response); } } } catch (ConnectTimeoutException cte) { log.error("请求通信[" + reqURL + "]时连接超时,堆栈轨迹如下", cte); } catch (SocketTimeoutException ste) { log.error("请求通信[" + reqURL + "]时读取超时,堆栈轨迹如下", ste); } catch (ClientProtocolException cpe) { log.error("请求通信[" + reqURL + "]时协议异常,堆栈轨迹如下", cpe); } catch (ParseException pe) { log.error("请求通信[" + reqURL + "]时解析异常,堆栈轨迹如下", pe); } catch (IOException ioe) { log.error("请求通信[" + reqURL + "]时网络异常,堆栈轨迹如下", ioe); } catch (Exception e) { log.error("请求通信[" + reqURL + "]时偶遇异常,堆栈轨迹如下", e); } finally { try { if (response != null) response.close(); } catch (IOException e) { e.printStackTrace(); } if (httpPost != null) { httpPost.releaseConnection(); } } return respContent; } }
第二种写法;
import java.io.IOException; import java.io.InterruptedIOException; import java.net.SocketTimeoutException; import java.net.UnknownHostException; import java.nio.charset.Charset; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import java.util.HashMap; import java.util.Map; import java.util.Set; import java.util.concurrent.TimeUnit; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLException; import javax.net.ssl.SSLHandshakeException; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; import org.apache.commons.lang3.StringUtils; import org.apache.http.Header; import org.apache.http.HeaderElement; import org.apache.http.HttpEntity; import org.apache.http.HttpEntityEnclosingRequest; import org.apache.http.HttpHeaders; import org.apache.http.HttpHost; import org.apache.http.HttpRequest; import org.apache.http.HttpResponse; import org.apache.http.NameValuePair; import org.apache.http.NoHttpResponseException; import org.apache.http.ParseException; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.HttpRequestRetryHandler; import org.apache.http.client.config.RequestConfig; 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.protocol.HttpClientContext; import org.apache.http.config.Registry; import org.apache.http.config.RegistryBuilder; import org.apache.http.config.SocketConfig; import org.apache.http.conn.ConnectTimeoutException; import org.apache.http.conn.routing.HttpRoute; import org.apache.http.conn.socket.ConnectionSocketFactory; import org.apache.http.conn.socket.LayeredConnectionSocketFactory; import org.apache.http.conn.socket.PlainConnectionSocketFactory; import org.apache.http.conn.ssl.NoopHostnameVerifier; import org.apache.http.conn.ssl.SSLConnectionSocketFactory; import org.apache.http.entity.ByteArrayEntity; import org.apache.http.entity.ContentType; import org.apache.http.entity.StringEntity; 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.pool.PoolStats; import org.apache.http.protocol.HTTP; import org.apache.http.protocol.HttpContext; import org.apache.http.util.EntityUtils; import org.apache.poi.util.IOUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.sinoeyes.common.IDictConst; import com.sinoeyes.web.entity.achieve.DownLoadFile; import net.sf.json.JSONObject; public class HttpClientUtil implements IDictConst { private static Logger logger = LoggerFactory.getLogger(HttpClientUtil.class); private final static int CONNECT_TIMEOUT = 4000; // 连接超时毫秒 private final static int SOCKET_TIMEOUT = 30000; // 传输超时毫秒 private final static int SOCKET_TIMEOUT_DELAY = 180000; // 最长传输超时毫秒 private final static int REQUESTCONNECT_TIMEOUT = 3000; // 获取请求超时毫秒 private final static int CONNECT_TOTAL = 800; // 最大连接数 private final static int CONNECT_ROUTE = 800; // 每个路由基础的连接数 private final static String ENCODE_CHARSET = "utf-8"; // 响应报文解码字符集 private final static String RESP_CONTENT = "通信失败"; public static PoolingHttpClientConnectionManager connManager = null; private static CloseableHttpClient httpClient = null; static { ConnectionSocketFactory plainsf = PlainConnectionSocketFactory.getSocketFactory(); LayeredConnectionSocketFactory sslsf = createSSLConnSocketFactory(); Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory> create().register("http", plainsf).register("https", sslsf).build(); connManager = new PoolingHttpClientConnectionManager(registry); // 将最大连接数增加到200 connManager.setMaxTotal(CONNECT_TOTAL); // 将每个路由基础的连接增加到20 connManager.setDefaultMaxPerRoute(CONNECT_ROUTE); // 可用空闲连接过期时间,重用空闲连接时会先检查是否空闲时间超过这个时间,如果超过,释放socket重新建立 connManager.setValidateAfterInactivity(30000); // 设置socket超时时间 SocketConfig socketConfig = SocketConfig.custom().setSoTimeout(SOCKET_TIMEOUT).build(); connManager.setDefaultSocketConfig(socketConfig); RequestConfig requestConfig = RequestConfig.custom().setConnectionRequestTimeout(REQUESTCONNECT_TIMEOUT).setConnectTimeout(CONNECT_TIMEOUT).setSocketTimeout(SOCKET_TIMEOUT) .build(); HttpRequestRetryHandler httpRequestRetryHandler = new HttpRequestRetryHandler() { @Override public boolean retryRequest(IOException exception, int executionCount, HttpContext context) { if (executionCount >= 3) {// 如果已经重试了3次,就放弃 return false; } if (exception instanceof NoHttpResponseException) {// 如果服务器丢掉了连接,那么就重试 return true; } if (exception instanceof SSLHandshakeException) {// 不要重试SSL握手异常 return false; } if (exception instanceof InterruptedIOException) {// 超时 return true; } if (exception instanceof UnknownHostException) {// 目标服务器不可达 return false; } if (exception instanceof ConnectTimeoutException) {// 连接被拒绝 return false; } if (exception instanceof SSLException) {// ssl握手异常 return false; } HttpClientContext clientContext = HttpClientContext.adapt(context); HttpRequest request = clientContext.getRequest(); // 如果请求是幂等的,就再次尝试 if (!(request instanceof HttpEntityEnclosingRequest)) { return true; } return false; } }; httpClient = HttpClients.custom().setConnectionManager(connManager).setDefaultRequestConfig(requestConfig).setRetryHandler(httpRequestRetryHandler).build(); if (connManager != null && connManager.getTotalStats() != null) { logger.info("now client pool " + connManager.getTotalStats().toString()); } } /** * 发送HTTP_GET请求 * * @see 1)该方法会自动关闭连接,释放资源 * @see 2)方法内设置了连接和读取超时时间,单位为毫秒,超时或发生其它异常时方法会自动返回"通信失败"字符串 * @see 3)请求参数含中文时,经测试可直接传入中文,HttpClient会自动编码发给Server,应用时应根据实际效果决 定传入前是否转码 * @see 4)该方法会自动获取到响应消息头中[Content-Type:text/html; charset=GBK]的charset值作为响应报文的 解码字符集 * @see 5)若响应消息头中无Content-Type属性,则会使用HttpClient内部默认的ISO-8859-1作为响应报文的解码字符 集 * @param reqURL 请求地址(含参数) * @return 远程主机响应正文 */ public static String sendGetRequest(String reqURL, String param) { if (null != param) { reqURL += "?" + param; } String respContent = RESP_CONTENT; // 响应内容 // reqURL = URLDecoder.decode(reqURL, ENCODE_CHARSET); HttpGet httpget = new HttpGet(reqURL); CloseableHttpResponse response = null; try { response = httpClient.execute(httpget, HttpClientContext.create()); // 执行GET请求 HttpEntity entity = response.getEntity(); // 获取响应实体 if (null != entity) { Charset respCharset = ContentType.getOrDefault(entity).getCharset(); respContent = EntityUtils.toString(entity, respCharset); EntityUtils.consume(entity); } } catch (ConnectTimeoutException cte) { logger.error("请求通信[" + reqURL + "]时连接超时,堆栈轨迹如下", cte); } catch (SocketTimeoutException ste) { logger.error("请求通信[" + reqURL + "]时读取超时,堆栈轨迹如下", ste); } catch (ClientProtocolException cpe) { // 该异常通常是协议错误导致:比如构造HttpGet对象时传入协议不对(将'http'写成'htp')or响应内容不符合HTTP协议要求等 logger.error("请求通信[" + reqURL + "]时协议异常,堆栈轨迹如下", cpe); } catch (ParseException pe) { logger.error("请求通信[" + reqURL + "]时解析异常,堆栈轨迹如下", pe); } catch (IOException ioe) { // 该异常通常是网络原因引起的,如HTTP服务器未启动等 logger.error("请求通信[" + reqURL + "]时网络异常,堆栈轨迹如下", ioe); } catch (Exception e) { logger.error("请求通信[" + reqURL + "]时偶遇异常,堆栈轨迹如下", e); } finally { try { if (response != null) response.close(); } catch (IOException e) { e.printStackTrace(); } if (httpget != null) { httpget.releaseConnection(); } } return respContent; } public static String sendPostRequest(String reqURL, String param) throws IOException { return sendPostRequest(reqURL, param, ""); } /** * 发送HTTP_POST请求 type: 默认是表单请求, * * @see 1)该方法允许自定义任何格式和内容的HTTP请求报文体 * @see 2)该方法会自动关闭连接,释放资源 * @see 3)方法内设置了连接和读取超时时间,单位为毫秒,超时或发生其它异常时方法会自动返回"通信失败"字符串 * @see 4)请求参数含中文等特殊字符时,可直接传入本方法,并指明其编码字符集encodeCharset参数,方法内部会自 动对其转码 * @see 5)该方法在解码响应报文时所采用的编码,取自响应消息头中的[Content-Type:text/html; charset=GBK]的 charset值 * @see 6)若响应消息头中未指定Content-Type属性,则会使用HttpClient内部默认的ISO-8859-1 * @param reqURL 请求地址 * @param param 请求参数,若有多个参数则应拼接为param11=value11&22=value22&33=value33的形式 * @param type 编码字符集,编码请求数据时用之,此参数为必填项(不能为""或null) * @return 远程主机响应正文 */ public static String sendPostRequest(String reqURL, String param, String type) { String result = RESP_CONTENT; // 设置请求和传输超时时间 HttpPost httpPost = new HttpPost(reqURL); // 这就有可能会导致服务端接收不到POST过去的参数,比如运行在Tomcat6.0.36中的Servlet,所以我们手工指定CONTENT_TYPE头消息 if (type != null && type.length() > 0) { httpPost.setHeader(HTTP.CONTENT_TYPE, "application/json; charset=" + ENCODE_CHARSET); } else { httpPost.setHeader(HTTP.CONTENT_TYPE, "application/x-www-form-urlencoded; charset=" + ENCODE_CHARSET); } CloseableHttpResponse response = null; try { if (param != null) { StringEntity entity = new StringEntity(param, ENCODE_CHARSET); httpPost.setEntity(entity); } logger.info("开始执行请求:" + reqURL); // reqURL = URLDecoder.decode(reqURL, ENCODE_CHARSET); response = httpClient.execute(httpPost, HttpClientContext.create()); HttpEntity entity = response.getEntity(); if (null != entity) { result = EntityUtils.toString(entity, ContentType.getOrDefault(entity).getCharset()); logger.info("执行请求完毕:" + result); EntityUtils.consume(entity); } } catch (ConnectTimeoutException cte) { logger.error("请求通信[" + reqURL + "]时连接超时,堆栈轨迹如下", cte); } catch (SocketTimeoutException ste) { logger.error("请求通信[" + reqURL + "]时读取超时,堆栈轨迹如下", ste); } catch (ClientProtocolException cpe) { logger.error("请求通信[" + reqURL + "]时协议异常,堆栈轨迹如下", cpe); } catch (ParseException pe) { logger.error("请求通信[" + reqURL + "]时解析异常,堆栈轨迹如下", pe); } catch (IOException ioe) { logger.error("请求通信[" + reqURL + "]时网络异常,堆栈轨迹如下", ioe); } catch (Exception e) { logger.error("请求通信[" + reqURL + "]时偶遇异常,堆栈轨迹如下", e); } finally { try { if (response != null) response.close(); } catch (IOException e) { e.printStackTrace(); } if (httpPost != null) { httpPost.releaseConnection(); } } return result; } /** * 上传文件 * * @param url * @param bodyBytes * @param boundary * @return * @throws ClientProtocolException * @throws IOException */ public static JSONObject uploadFile(String url, byte[] bodyBytes, String boundary) throws ClientProtocolException, IOException { if (null != connManager) { connManager.closeExpiredConnections(); connManager.closeIdleConnections(180L, TimeUnit.SECONDS); } JSONObject result = new JSONObject(); HttpPost post = new HttpPost(url); post.setHeader(HttpHeaders.CONNECTION, "close"); RequestConfig requestConfig = doProxy(true, false); post.setConfig(requestConfig); post.addHeader("Content-Type", "multipart/form-data; boundary=" + boundary); post.setEntity(new ByteArrayEntity(bodyBytes)); CloseableHttpResponse response = null; try { response = httpClient.execute(post); int code = response.getStatusLine().getStatusCode(); if (code == 200) { HttpEntity entity = response.getEntity(); byte[] entityByte = EntityUtils.toByteArray(entity); byte[] entityStr = AesUtil.decrypt(entityByte); EntityUtils.consume(entity); if (null != entityStr && entityStr.length > 0) {// 正常解密 result = JSONObject.fromObject(new String(entityStr, ENCODE_CHARSET)); } else { // 解密失败 String s = new String(entityByte, ENCODE_CHARSET); if (StringUtils.isNotBlank(s) && StringUtils.startsWith(s, "{")) { result = JSONObject.fromObject(s); } else { result.put(ERROR_CODE, ERROR_EXCEPTION); result.put(ERROR_MESSAGE, s); } } return result; } else { result.put(ERROR_CODE, code); result.put(ERROR_MESSAGE, "请求失败!"); } } catch (Exception e) { e.printStackTrace(); result.put(ERROR_CODE, ERROR_EXCEPTION); result.put(ERROR_MESSAGE, e.getMessage()); } finally { if (response != null) { EntityUtils.consumeQuietly(response.getEntity()); } if (post != null) { post.releaseConnection(); } } return result; } /** * 正常httpclent请求 * * @param reqURL * @param json * @param isProxy * @return */ public static JSONObject sendPostRequest(String reqURL, JSONObject json, boolean isProxy) { return sendPostRequestCommon(reqURL, json, isProxy, false); } /** * 加长传输时间httpclent请求 * * @param reqURL * @param json * @param isProxy * @return */ public static JSONObject sendPostRequestSlow(String reqURL, JSONObject json, boolean isProxy) { return sendPostRequestCommon(reqURL, json, isProxy, true); } /** * 下载文件功能 * * @param url * @param json * @return */ public static DownLoadFile downLoadFile(String url, String json) { if (null != connManager) { connManager.closeExpiredConnections(); connManager.closeIdleConnections(180L, TimeUnit.SECONDS); } byte[] encryptByte = AesUtil.encrypt(json); HttpPost post = new HttpPost(url); RequestConfig requestConfig = doProxy(true, false); post.setHeader(HttpHeaders.CONNECTION, "close"); post.setConfig(requestConfig); post.setEntity(new ByteArrayEntity(encryptByte)); CloseableHttpResponse response = null; DownLoadFile file = new DownLoadFile(); try { response = httpClient.execute(post); if (response.getStatusLine().getStatusCode() == 200) { HttpEntity entity = response.getEntity(); if (entity.getContentType().getValue().contains("application/octet-stream")) { byte[] toByte = IOUtils.toByteArray(response.getEntity().getContent()); byte[] derByte = AesUtil.decrypt(toByte); file.setError_code(0); file.setError_message("ok"); file.setBytes(derByte); file.setFileName(getFileName(response)); file.setContentType(entity.getContentType().getValue()); return file; } else if (response.getEntity().getContentType().getValue().contains("text/plain")) { byte[] entityByte = EntityUtils.toByteArray(response.getEntity()); byte[] entityStr = AesUtil.decrypt(entityByte); JSONObject jsonResult; if (null != entityStr && entityStr.length > 0) { jsonResult = JSONObject.fromObject(new String(entityStr, ENCODE_CHARSET)); } else { String s = new String(entityByte, ENCODE_CHARSET); logger.info("下载文件返回的字符串是:{}", s); jsonResult = JSONObject.fromObject(s); } file.setError_code(jsonResult.getInt(ERROR_CODE)); file.setError_message(jsonResult.getString(ERROR_MESSAGE)); return file; } } } catch (Exception e) { file.setError_code(ERROR_EXCEPTION); file.setError_message(e.getMessage()); logger.error(e.getMessage(), e); } finally { if (response != null) { EntityUtils.consumeQuietly(response.getEntity()); } if (post != null) { post.releaseConnection(); } } return file; } /** * 获取Header标头中的filename,文件名称 * * @param response * @return */ public static String getFileName(HttpResponse response) { Header contentHeader = response.getFirstHeader("Content-Disposition"); String filename = null; if (contentHeader != null) { HeaderElement[] values = contentHeader.getElements(); if (values.length == 1) { NameValuePair param = values[0].getParameterByName("filename"); if (param != null) { try { filename = new String(param.getValue().getBytes("iso-8859-1"), ENCODE_CHARSET); } catch (Exception e) { e.printStackTrace(); } } } } return filename; } /** * 代理设置 * * @param isProxy * @return */ private static RequestConfig doProxy(boolean isProxy, boolean delay) { RequestConfig.Builder configBuilder = RequestConfig.custom().setConnectTimeout(CONNECT_TIMEOUT).setSocketTimeout(SOCKET_TIMEOUT); if (delay) { configBuilder.setSocketTimeout(SOCKET_TIMEOUT_DELAY); } if (CloudBootStrapUtils.PROXY_START && isProxy) { HttpHost proxy = new HttpHost(CloudBootStrapUtils.PROXY_ADDRESS, CloudBootStrapUtils.PROXY_PORT); configBuilder.setProxy(proxy); } return configBuilder.build(); } /** * 发送post请求 * * @param reqURL * @param json * @param isProxy * @return */ private static JSONObject sendPostRequestCommon(String reqURL, JSONObject json, boolean isProxy, boolean delay) { if (null != connManager) { connManager.closeExpiredConnections(); connManager.closeIdleConnections(180L, TimeUnit.SECONDS); } PoolStats poolStats; if (connManager != null && (poolStats = connManager.getTotalStats()) != null) { if (poolStats.getLeased() > 100 || poolStats.getPending() > 1) { logger.info("now client pool {}", poolStats); } } JSONObject jsonResult = new JSONObject(); // 创建HTTP请求 HttpPost post = new HttpPost(reqURL); post.setHeader(HttpHeaders.CONNECTION, "close"); // 参数AEC加密 byte[] encryptByte = AesUtil.encrypt(json.toString()); if (isProxy) { RequestConfig requestConfig = doProxy(isProxy, delay); if (null != requestConfig) { post.setConfig(requestConfig); } } // 设置访问字节型 post.setEntity(new ByteArrayEntity(encryptByte)); CloseableHttpResponse response = null; try { response = httpClient.execute(post); HttpEntity entity = response.getEntity(); if (response.getStatusLine().getStatusCode() == 200 && null != entity) { byte[] entityByte = EntityUtils.toByteArray(entity); byte[] entityStr = AesUtil.decrypt(entityByte); EntityUtils.consume(entity); if (null != entityStr && entityStr.length > 0) {// 正常解密 jsonResult = JSONObject.fromObject(new String(entityStr, ENCODE_CHARSET)); } else { // 解密失败 String s = new String(entityByte, ENCODE_CHARSET); if (StringUtils.isNotBlank(s) && StringUtils.startsWith(s, "{")) { jsonResult = JSONObject.fromObject(s); } else { jsonResult.put(ERROR_CODE, ERROR_EXCEPTION); jsonResult.put(ERROR_MESSAGE, s); } } return jsonResult; } jsonResult.put(ERROR_CODE, response.getStatusLine().getStatusCode()); jsonResult.put(ERROR_MESSAGE, response.getStatusLine().toString()); } catch (Exception e) { jsonResult.put(ERROR_CODE, ERROR_EXCEPTION); jsonResult.put(ERROR_MESSAGE, e.getMessage()); } finally { if (response != null) { EntityUtils.consumeQuietly(response.getEntity()); } if (post != null) { post.releaseConnection(); } } return jsonResult; } /** * SSL的socket工厂创建 */ private static SSLConnectionSocketFactory createSSLConnSocketFactory() { SSLConnectionSocketFactory sslsf = null; // 创建TrustManager() 用于解决javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated X509TrustManager trustManager = new X509TrustManager() { @Override public X509Certificate[] getAcceptedIssuers() { return null; } @Override public void checkClientTrusted(X509Certificate[] arg0, String authType) throws CertificateException { } @Override public void checkServerTrusted(X509Certificate[] arg0, String authType) throws CertificateException { } }; SSLContext sslContext; try { sslContext = SSLContext.getInstance(SSLConnectionSocketFactory.TLS); sslContext.init(null, new TrustManager[] { (TrustManager) trustManager }, null); // 创建SSLSocketFactory , // 不校验域名 ,取代以前验证规则 sslsf = new SSLConnectionSocketFactory(sslContext, NoopHostnameVerifier.INSTANCE); } catch (Exception e) { logger.error(e.getMessage(), e); } return sslsf; } /** * httpclent连接池的状态 * * @return */ public static Map<HttpRoute, PoolStats> getConnManagerStats() { if (connManager != null) { Set<HttpRoute> routeSet = connManager.getRoutes(); if (routeSet != null && !routeSet.isEmpty()) { Map<HttpRoute, PoolStats> routeStatsMap = new HashMap<HttpRoute, PoolStats>(); for (HttpRoute route : routeSet) { PoolStats stats = connManager.getStats(route); routeStatsMap.put(route, stats); } return routeStatsMap; } } return null; } /** * 获取当前连接池的状态 * * @return */ public static PoolStats getConnManagerTotalStats() { if (connManager != null) { return connManager.getTotalStats(); } return null; } /** * 关闭系统时关闭httpClient */ public static void releaseHttpClient() { try { httpClient.close(); } catch (IOException e) { logger.error("关闭httpClient异常" + e); } finally { if (connManager != null) { connManager.shutdown(); } } } }