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<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>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<Header> defaultHeaders=new ArrayList<Header>(); 
 | 
        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<String, Object> 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<String, Object> 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<String, Object> heads, Map<String, Object> 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<String> res=new ResultInfo<String>(); 
 | 
                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<String, Object> heads, Map<String, Object> 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<String> res=new ResultInfo<String>(); 
 | 
                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<String, Object> heads, Map<String, Object> 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<String, Object> 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<NameValuePair> pList = new ArrayList<NameValuePair>(); 
 | 
            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<String, Object> heads, Map<String, Object> 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<String> res=new ResultInfo<String>(); 
 | 
                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<String, Object> heads, Map<String, Object> 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<String> res=new ResultInfo<String>(); 
 | 
                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<String, Object> heads, Map<String, Object> 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<String> res=new ResultInfo<String>(); 
 | 
                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) {} 
 | 
        } 
 | 
    } 
 | 
} 
 |