package com.jzq.common.http; import com.alibaba.fastjson.JSONObject; import com.jzq.common.CommonUtil; import com.jzq.common.ResultInfo; import com.jzq.common.exception.ResultInfoException; import org.apache.commons.lang3.StringUtils; import org.apache.http.*; import org.apache.http.client.HttpRequestRetryHandler; 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.methods.HttpRequestBase; import org.apache.http.client.utils.URIBuilder; import org.apache.http.config.ConnectionConfig; 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.conn.ssl.TrustSelfSignedStrategy; import org.apache.http.entity.ContentType; import org.apache.http.entity.mime.MultipartEntityBuilder; import org.apache.http.entity.mime.content.ByteArrayBody; import org.apache.http.entity.mime.content.FileBody; import org.apache.http.entity.mime.content.InputStreamBody; import org.apache.http.entity.mime.content.StringBody; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import org.apache.http.impl.client.LaxRedirectStrategy; import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; import org.apache.http.message.BasicHeader; import org.apache.http.message.BasicNameValuePair; import org.apache.http.protocol.ExecutionContext; import org.apache.http.protocol.HttpContext; import org.apache.http.ssl.SSLContexts; import org.apache.http.util.EntityUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLException; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; import java.io.File; import java.io.IOException; import java.io.InterruptedIOException; import java.io.UnsupportedEncodingException; import java.net.ConnectException; import java.net.URI; import java.net.URISyntaxException; import java.net.UnknownHostException; import java.nio.charset.CodingErrorAction; import java.security.KeyManagementException; import java.security.KeyStore; 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; /** * http的请求服务类 * 也可以考虑使用spring restTemplate调用 */ public class HttpClientUtils { public static Logger logger = LoggerFactory.getLogger(HttpClientUtils.class); private static Object objTg = new Object(); private static HttpClientUtils httpClientUtils; /** * 默认连接超时时间 */ private final static int DEFAULT_CONN_TIMEOUT = 6000; /**最大重试次数*/ private final static int DEFAULT_RETRY_TIMES = 3; private CloseableHttpClient client; /** * ssl trust管理 */ public static class SSLTrustAllManager implements 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; } } /** * 初始化ssl管理 * @return * @throws KeyStoreException * @throws CertificateException * @throws NoSuchAlgorithmException * @throws IOException * @throws KeyManagementException */ private SSLConnectionSocketFactory initSSLConnectionSocketFactory() throws KeyStoreException, CertificateException, NoSuchAlgorithmException, IOException, KeyManagementException { KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType()); trustStore.load(null, null); SSLContext sslcontext = SSLContexts.custom() .loadTrustMaterial(trustStore, new TrustSelfSignedStrategy()) .build(); sslcontext.init(null, new TrustManager[] { new SSLTrustAllManager() }, null); SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory( sslcontext, //new String[] { "TLSv1","TLSv1.1","TLSv1.2","SSLv3"},//参考ProtocolVersion//这里写为null为所有 null, null, SSLConnectionSocketFactory.getDefaultHostnameVerifier()); return sslsf; } public HttpClientUtils() throws Exception { // 设置协议http和https对应的处理socket链接工厂的对象 Registry socketFactoryRegistry = RegistryBuilder.create() .register("http", PlainConnectionSocketFactory.INSTANCE) .register("https", initSSLConnectionSocketFactory()) .build(); PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry); connManager.setValidateAfterInactivity(1000); ConnectionConfig connectionConfig = ConnectionConfig.custom() .setMalformedInputAction(CodingErrorAction.IGNORE) .setUnmappableInputAction(CodingErrorAction.IGNORE) .setCharset(Consts.UTF_8) .build(); connManager.setDefaultConnectionConfig(connectionConfig); connManager.setMaxTotal(100); connManager.setDefaultMaxPerRoute(10);//最大路由深度,即301次数 //默认头信息,创建自定义的httpclient对象 List
defaultHeaders=new ArrayList
(); defaultHeaders.add(new BasicHeader("Accept","text/html,application/xhtml+xml,application/xml,application/json;q=0.9,*/*;q=0.8")); defaultHeaders.add(new BasicHeader("Accept-Language","zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2")); defaultHeaders.add(new BasicHeader("Connection","close")); defaultHeaders.add(new BasicHeader("User-Agent","Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:59.0) Gecko/20100101 Firefox/59.0")); //默认请求配置 RequestConfig requestConfig = RequestConfig.custom() .setSocketTimeout(DEFAULT_CONN_TIMEOUT) .setConnectTimeout(DEFAULT_CONN_TIMEOUT) //.setProxy(new HttpHost("myotherproxy", 8080)) //设置代理 .setConnectionRequestTimeout(DEFAULT_CONN_TIMEOUT).build(); //重试拦截 HttpRequestRetryHandler myRetryHandler = new HttpRequestRetryHandler() { @Override public boolean retryRequest(IOException exception, int executionCount, HttpContext context) { if (executionCount >= DEFAULT_RETRY_TIMES) { //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 ConnectException) { // Connection refused return false; } if (exception instanceof SSLException) { // SSL handshake exception return false; } HttpRequest request = (HttpRequest) context.getAttribute(ExecutionContext.HTTP_REQUEST); boolean idempotent = !(request instanceof HttpEntityEnclosingRequest); if (idempotent) { return true; } return false; } }; client = HttpClients.custom() .setConnectionManager(connManager) .setDefaultHeaders(defaultHeaders) .setDefaultRequestConfig(requestConfig) .setRetryHandler(myRetryHandler) .setRedirectStrategy(new LaxRedirectStrategy()) .build(); } /** * init实例 * @return */ public static HttpClientUtils init(){ synchronized (objTg) { if (httpClientUtils == null) { try { httpClientUtils = new HttpClientUtils(); } catch (Exception e) { throw new ResultInfoException("ACCESS_SIGN_ERROR","httpClient初始化出错",e); } } } return httpClientUtils; } /** * 工具类,通过url和params 生成url地址 * @param url * @param params * @return * @throws URISyntaxException */ public static URI builderUrl(String url, Map params){ URIBuilder builder = null; try { builder = new URIBuilder(url); if(params!=null&¶ms.size()>0){ for(String key: params.keySet()){ Object obj=params.get(key); if(obj==null){continue;} builder.setParameter(key, CommonUtil.parValNoErr(obj, String.class)); } } return builder.build(); } catch (URISyntaxException e) { throw new ResultInfoException("HTTP_URL_FORMART","转换地址出错:"+url,e); } } public static void fillHeader(HttpRequestBase request, Map heads){ //请求头 if (heads != null && heads.size() > 0) { for (String key : heads.keySet()) { request.addHeader(key, heads.get(key) + ""); } } } /** * get请求 * @param uri * @param heads * @param params * @return * @throws Exception */ public String getGet(String uri, Map heads, Map params) { HttpGet request = new HttpGet(builderUrl(uri,params)); fillHeader(request,heads); CloseableHttpResponse response = null; try { response = client.execute(request); if (response.getStatusLine().getStatusCode() == 200) { // 获得返回的字符串 String result = EntityUtils.toString(response.getEntity(), "UTF-8"); return result; } else { String result = EntityUtils.toString(response.getEntity(), "UTF-8"); result= StringUtils.isNotBlank(result)?result.substring(0,result.length()>200?200:result.length()) : ""; ResultInfo res=new ResultInfo(); res.setData(result); res.setSuccess(false); res.setResultCode(response.getStatusLine().getStatusCode()+""); throw new ResultInfoException("HTTP_RESPONSE_ERROR", JSONObject.toJSONString(res)); } } catch (IOException e) { throw new ResultInfoException("EXCEPTION","网络请求失败",e); } finally { try { response.close(); } catch (Exception e) {} } } public byte[] getGetByte(String uri, Map heads, Map params) { HttpGet request = new HttpGet(builderUrl(uri,params)); fillHeader(request,heads); CloseableHttpResponse response = null; try { response = client.execute(request); if (response.getStatusLine().getStatusCode() == 200) { // 获得返回的字符串 byte[] result = EntityUtils.toByteArray(response.getEntity()); return result; } else { ResultInfo res=new ResultInfo(); res.setSuccess(false); res.setResultCode(response.getStatusLine().getStatusCode()+""); throw new ResultInfoException("HTTP_RESPONSE_ERROR", JSONObject.toJSONString(res)); } } catch (IOException e) { throw new ResultInfoException("EXCEPTION","网络请求失败",e); } finally { try { response.close(); } catch (Exception e) {} } } /** * 直接获取返回体,注意要手动关闭response * @param uri * @param heads * @param params * @return */ public CloseableHttpResponse getGetResponse(String uri, Map heads, Map params) throws IOException { HttpGet request = new HttpGet(builderUrl(uri,params)); fillHeader(request,heads); CloseableHttpResponse response = null; response = client.execute(request); return response; } /** * 构建post的body信息, * @param request * @param params * @param ifMutipart 是否启用富文件方式上传 */ private void buildPostBody(HttpPost request, Map params, boolean ifMutipart){ if(ifMutipart){ //富文本请求 MultipartEntityBuilder meBuiler = MultipartEntityBuilder.create(); if (params != null && params.size() > 0) { for (String key : params.keySet()) { Object obj = params.get(key); if(obj==null){ continue; }else if (obj instanceof File) { FileBody fb = new FileBody((File) obj); meBuiler.addPart(key, fb); } else if (obj instanceof ByteArrayBody) { meBuiler.addPart(key, (ByteArrayBody) obj); } else if (obj instanceof FileBody) { meBuiler.addPart(key, (FileBody) obj); } else if (obj instanceof InputStreamBody) { meBuiler.addPart(key, (InputStreamBody) obj); }else { StringBody sb = new StringBody(CommonUtil.parValNoErrDef(obj, String.class, ""), ContentType.create("text/plain", "UTF-8")); meBuiler.addPart(key, sb); } } } HttpEntity httpEntity = meBuiler.build(); request.setEntity(httpEntity); }else{ //普通请求 List pList = new ArrayList(); if (params != null && params.size() > 0) { for (String key : params.keySet()) { Object obj=params.get(key); if(obj==null){continue;} pList.add(new BasicNameValuePair(key, obj + "")); } } try { request.setEntity(new UrlEncodedFormEntity(pList, "UTF-8")); } catch (UnsupportedEncodingException e) { throw new ResultInfoException("HTTP_REQ_ENCODE_ERROR","请求参数格式化出错",e); } } } /** * post的上传请求 * @param uri * @param heads * @param params * @return * @throws Exception */ public String getPost(String uri, Map heads, Map params, boolean ifMutipart) { HttpPost request = new HttpPost(uri); fillHeader(request,heads); buildPostBody(request,params,ifMutipart); CloseableHttpResponse response = null; try { response = client.execute(request); if (response.getStatusLine().getStatusCode() == 200) { // 获得返回的字符串 String result = EntityUtils.toString(response.getEntity(), "UTF-8"); return result; } else { String result = EntityUtils.toString(response.getEntity(), "UTF-8"); result= StringUtils.isNotBlank(result) ?result.substring(0,result.length()>200?200:result.length()) : ""; ResultInfo res=new ResultInfo(); res.setData(result); res.setSuccess(false); res.setResultCode(response.getStatusLine().getStatusCode()+""); throw new ResultInfoException("HTTP_RESPONSE_ERROR", JSONObject.toJSONString(res)); } } catch (IOException e) { throw new ResultInfoException("HTTP_IO_ERROR","网络请求失败",e); } finally { try { response.close(); } catch (Exception e) {} } } /** * post的上传请求,返回byte[] * @param uri * @param heads * @param params * @return * @throws Exception */ public byte[] getPostByte(String uri, Map heads, Map params, boolean ifMutipart) { HttpPost request = new HttpPost(uri); fillHeader(request,heads); buildPostBody(request,params,ifMutipart); CloseableHttpResponse response = null; try { response = client.execute(request); if (response.getStatusLine().getStatusCode() == 200) { // 获得返回的byte[] byte[] result = EntityUtils.toByteArray(response.getEntity()); return result; } else { ResultInfo res=new ResultInfo(); res.setSuccess(false); res.setResultCode(response.getStatusLine().getStatusCode()+""); throw new ResultInfoException("HTTP_RESPONSE_ERROR", JSONObject.toJSONString(res)); } } catch (IOException e) { throw new ResultInfoException("HTTP_IO_ERROR","网络请求失败",e); } finally { try { response.close(); } catch (Exception e) {} } } /** * post的上传请求,返回CloseableHttpResponse,必须手动关闭 * @param uri * @param heads * @param params * @return * @throws Exception */ public CloseableHttpResponse getPostResponse(String uri, Map heads, Map params, boolean ifMutipart) { HttpPost request = new HttpPost(uri); fillHeader(request,heads); buildPostBody(request,params,ifMutipart); CloseableHttpResponse response = null; try { response = client.execute(request); if (response.getStatusLine().getStatusCode() == 200) { return response; } else { String result = EntityUtils.toString(response.getEntity(), "UTF-8"); result= StringUtils.isNotBlank(result)?result.substring(0,result.length()>200?200:result.length()) : ""; ResultInfo res=new ResultInfo(); res.setData(result); res.setSuccess(false); res.setResultCode(response.getStatusLine().getStatusCode()+""); throw new ResultInfoException("HTTP_RESPONSE_ERROR", JSONObject.toJSONString(res)); } } catch (IOException e) { throw new ResultInfoException("HTTP_IO_ERROR","网络请求失败",e); } finally { try { response.close(); } catch (Exception e) {} } } }