HttpURLConnection使用

import com.google.common.collect.Lists;
import com.meiyunji.spider.contant.HttpConnectContant;
import com.meiyunji.spider.crawl.response.HeaderVo;
import com.meiyunji.spider.crawl.response.ResponseObj;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpStatus;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.net.ssl.*;
import java.io.*;
import java.net.*;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.List;
import java.util.Map;
import java.util.zip.GZIPInputStream;

/**
 * @author ldj
 * @date 2018/6/25.
 * <p>
 * 使用 httpUrlConnection请求信息
 */
public class HttpConnectUtil {

    private static final Logger logger = LoggerFactory.getLogger(HttpConnectUtil.class);

    /**
     * Get 方法
     *
     * @param url        请求连接
     * @param ip         本次请求使用的ip
     * @param headers    请求头, 为空会填写默认头部信息
     * @param parameters 请求体,
     * @return ResponseObj 返回结果
     **/
    public static ResponseObj urlGet(String url, String ip, Map<String, String> headers, Map<String, String> parameters) {
        return urlBaseGet(url, ip, null, headers, parameters);
    }

    /**
     * 代理请求
     *
     * @param url        请求连接
     * @param ip         代理ip
     * @param port       代理端口
     * @param headers    请求头, 为空会填写默认头部信息
     * @param parameters 请求体,
     * @return ResponseObj 返回结果
     */
    public static ResponseObj urlPorxyGet(String url, String ip, Integer port, Map<String, String> headers, Map<String, String> parameters) {
        return urlBaseGet(url, ip, port, headers, parameters);
    }

    /**
     * Get 请求
     */
    private static ResponseObj urlBaseGet(String url, String ip, Integer port, Map<String, String> headers, Map<String, String> parameters) {

        ResponseObj responseObj;
        try {
            url = url.trim();
            if (parameters != null) {
                StringBuilder sbd = new StringBuilder(url);
                parameters.forEach((key, value) -> sbd.append(StringUtils.containsIgnoreCase(sbd, "?") ? "?" : "&").append(key).append("=").append(value));
                url = sbd.toString();
            }
            URL requestUrl = new URL(url);
            if (HttpConnectContant.CONNECT_TYPE_HTTPS.equalsIgnoreCase(requestUrl.getProtocol())) {
                responseObj = httpsConnectionGet(requestUrl, ip, port, headers, parameters);
            } else {
                responseObj = httpConnectionGet(requestUrl, ip, port, headers, parameters);
            }
        } catch (IOException e) {
            responseObj = new ResponseObj();
            responseObj.setStatusCode(-1);
            responseObj.setReasonPhrase("Crawl Error : URL DealHtml error, the url is not support request.");
        }
        responseObj.setIp(ip);
        responseObj.setUrl(url);

        logger.info("url: {}", url);
        logger.info("statusCode: {}", responseObj.getStatusCode());
        logger.info("message: {}", responseObj.getReasonPhrase());
        return responseObj;
    }

    /**
     * Https Get 方法
     *
     * @param  requestUrl 请求连接
     * @param ip 本次请求使用的ip
     * @param headers 请求头, 为空会填写默认头部信息
     * @param parameters 请求体,
     * @return  ResponseObj 返回结果
     * String ua,
     * String html,
     * String statusCode,
     * String ip;
     * String url;
     * String userAgent;
     */
    private static ResponseObj httpsConnectionGet(URL requestUrl, String ip, Integer port, Map<String, String> headers, Map<String, String> parameters) {
        InputStreamReader reader = null;
        GZIPInputStream gzipInputStream = null;
        InputStream inputStream = null;
        HttpsURLConnection httpsURLConnection = null;
        ResponseObj responseObj = new ResponseObj();
        try {
            // 获取 URLConnection对象
            httpsURLConnection = (HttpsURLConnection) getUrlConnection(requestUrl, ip, port);
            setDefaultProperties(httpsURLConnection);
            httpsURLConnection.setRequestMethod(HttpConnectContant.GET);

            if (headers == null || headers.size() == 0) {
                setDefaultHeader(httpsURLConnection);
            } else {
                setCustomizedHeader(httpsURLConnection, headers);
            }

            /// 设置绕过https验证
            trustAllHosts(httpsURLConnection);
            httpsURLConnection.setHostnameVerifier(DO_NOT_VARIFY);

            // 打开链接
            httpsURLConnection.connect();

            // 获取结果
            if (httpsURLConnection.getResponseCode() == HttpStatus.SC_OK || httpsURLConnection.getResponseCode() == HttpStatus.SC_CREATED) {
                inputStream = httpsURLConnection.getInputStream();
            } else {
                inputStream = httpsURLConnection.getErrorStream();
            }
            String contentEncoding = httpsURLConnection.getContentEncoding();
            if (contentEncoding != null && "gzip".equals(contentEncoding.trim().toLowerCase())) {
                gzipInputStream = new GZIPInputStream(inputStream);
                reader = new InputStreamReader(gzipInputStream);
            } else {
                reader = new InputStreamReader(inputStream);
            }

            StringBuilder sbfs = new StringBuilder();
            char[] c = new char[1024];
            int len;
            while (0 < (len = reader.read(c))) {
                sbfs.append(c, 0, len);
            }
            List<HeaderVo> headerList = Lists.newArrayList();
            Map<String, List<String>> responseHeaderFields = httpsURLConnection.getHeaderFields();
            if (responseHeaderFields != null && responseHeaderFields.size() > 0) {
                responseHeaderFields.forEach((key, value) -> headerList.add(new HeaderVo(key, JsonUtil.objectToJson(value))));
            }

            responseObj.setStatusCode(httpsURLConnection.getResponseCode());
            responseObj.setContent(sbfs.toString());
            responseObj.setResponseHeader(headerList);
            responseObj.setUserAgent(httpsURLConnection.getRequestProperty("user-agent"));

        } catch (IOException e) {
            e.printStackTrace();
            responseObj.setStatusCode(-1);
            responseObj.setReasonPhrase("Crawl Error : HttpsUrlConnection IOException .");
        } finally {
            try {
                if (reader != null) {
                    reader.close();
                }
                if (gzipInputStream != null) {
                    gzipInputStream.close();
                }
                if (inputStream != null) {
                    inputStream.close();
                }
                if (httpsURLConnection != null) {
                    httpsURLConnection.disconnect();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return responseObj;
    }

    /**
     * Http Get 方法
     *
     * @param  requestUrl 请求连接
     * @param ip 本次请求使用的ip
     * @param headers 请求头, 为空会填写默认头部信息
     * @param parameters 请求体,
     * @return  ResponseObj 返回结果
     * String ua,
     * String html,
     * String statusCode,
     * String ip;
     * String url;
     * URL requestUrl;
     * String userAgent;
     */
    private static ResponseObj httpConnectionGet(URL requestUrl, String ip, Integer port, Map<String, String> headers, Map<String, String> parameters) {
        InputStreamReader reader = null;
        GZIPInputStream gzipInputStream = null;
        InputStream inputStream = null;
        HttpURLConnection httpUrlConnection = null;
        ResponseObj responseObj = new ResponseObj();
        try {
            httpUrlConnection = (HttpURLConnection) getUrlConnection(requestUrl, ip, port);
            setDefaultProperties(httpUrlConnection);
            httpUrlConnection.setRequestMethod(HttpConnectContant.GET);
            if (headers == null || headers.size() <= 0) {
                setDefaultHeader(httpUrlConnection);
            } else {
                setCustomizedHeader(httpUrlConnection, headers);
            }

            httpUrlConnection.connect();

            if (httpUrlConnection.getResponseCode() == HttpStatus.SC_OK || httpUrlConnection.getResponseCode() == HttpStatus.SC_CREATED) {
                inputStream = httpUrlConnection.getInputStream();
            } else {
                inputStream = httpUrlConnection.getErrorStream();
            }
            String contentEncoding = httpUrlConnection.getContentEncoding();
            if (contentEncoding != null && "gzip".equals(contentEncoding.trim().toLowerCase())) {
                gzipInputStream = new GZIPInputStream(inputStream);
                reader = new InputStreamReader(gzipInputStream);
            } else {
                reader = new InputStreamReader(inputStream);
            }
            StringBuilder sbfs = new StringBuilder();
            char[] c = new char[1024];
            int len;
            while (0 < (len = reader.read(c))) {
                sbfs.append(c, 0, len);
            }

            List<HeaderVo> headerList = Lists.newArrayList();
            httpUrlConnection.getHeaderFields().forEach((key, value) -> headerList.add(new HeaderVo(key, JsonUtil.objectToJson(value))));
            responseObj.setStatusCode(httpUrlConnection.getResponseCode());
            responseObj.setContent(sbfs.toString());
            responseObj.setResponseHeader(headerList);
            responseObj.setUrl(requestUrl.getProtocol() + "://" + requestUrl.getHost() + requestUrl.getPath());
            if (headers != null) {
                responseObj.setUserAgent(headers.get("user_agent"));
            }

        } catch (IOException e) {
            responseObj.setStatusCode(-1);
            responseObj.setReasonPhrase("Crawl Error : HttpsUrlConnection IOException .");
        } finally {
            try {
                if (reader != null) {
                    reader.close();
                }
                if (gzipInputStream != null) {
                    gzipInputStream.close();
                }
                if (inputStream != null) {
                    inputStream.close();
                }
                if (httpUrlConnection != null) {
                    httpUrlConnection.disconnect();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return responseObj;
    }

    /**
     * POST 请求方式
     * 默认以JSON的形式传递数据
     */
    public static ResponseObj urlPost(String url, String ip, Map<String, String> headers, Map<String, String> bodyMap) {
        return urlAdvancedPost(url, ip, headers, bodyMap, HttpConnectContant.POST_BODY_TYPE_JSON);
    }

    /**
     * POST 走代理请求
     */
    public static ResponseObj urlProxyPost(String url, String ip, Integer port, Map<String, String> headers, Map<String, String> bodyMap) {
        return urlAdvancedPost(url, ip, headers, bodyMap, HttpConnectContant.POST_BODY_TYPE_JSON);
    }

    /**
     * POST请求方式
     *
     * @param url       请求连接
     * @param ip        请求ip
     * @param headers   请求头
     * @param bodyMap   请求体
     * @param submiType 提交数据方式  format / json
     */
    public static ResponseObj urlAdvancedPost(String url, String ip, Map<String, String> headers, Map<String, String> bodyMap, String submiType) {
        return urlBasePost(url, ip, null, headers, bodyMap, submiType);
    }

    /**
     * POST 代理请求方式
     *
     * @param url        请求连接
     * @param ip         代理请求ip
     * @param port       代理请求端口
     * @param headers    请求头
     * @param bodyMap    请求体
     * @param submitType 提交数据方式  format / json
     */
    public static ResponseObj urlAdvancedProxyPost(String url, String ip, Integer port, Map<String, String> headers, Map<String, String> bodyMap, String submitType) {
        return urlBasePost(url, ip, port, headers, bodyMap, submitType);
    }

    private static ResponseObj urlBasePost(String url, String ip, Integer port, Map<String, String> headers, Map<String, String> bodyMap, String submitType) {
        ResponseObj responseObj;
        try {
            URL requestUrl = new URL(url);
            if (HttpConnectContant.CONNECT_TYPE_HTTPS.equalsIgnoreCase(requestUrl.getProtocol())) {
                responseObj = httpsConnectionPost(requestUrl, ip, port, headers, bodyMap, submitType);
            } else {
                responseObj = httpConnectionPost(requestUrl, ip, port, headers, bodyMap, submitType);
            }
        } catch (IOException e) {
            responseObj = new ResponseObj();
            responseObj.setStatusCode(-1);
            responseObj.setReasonPhrase("Crawl Error : URL DealHtml error, the url is not support request.");
        }
        responseObj.setIp(ip);
        responseObj.setUrl(url);
        logger.info("url: {}", url);
        logger.info("statusCode: {}", responseObj.getStatusCode());
        logger.info("message: {}", responseObj.getReasonPhrase());
        return responseObj;
    }

    /**
     * https POST方法
     */
    private static ResponseObj httpsConnectionPost(URL requestUrl, String ip, Integer port, Map<String, String> headers, Map<String, String> bodyMap, String submitType) {
        Reader reader = null;
        GZIPInputStream gzipInputStream = null;
        InputStream inputStream = null;
        HttpsURLConnection httpsURLConnection = null;
        ResponseObj responseObj = new ResponseObj();
        try {
            httpsURLConnection = (HttpsURLConnection) getUrlConnection(requestUrl, ip, port);
            httpsURLConnection.setRequestMethod(HttpConnectContant.POST);

            // 设置默认请求属性
            setDefaultProperties(httpsURLConnection);
            httpsURLConnection.setUseCaches(false);

            // 绕过 https 验证
            trustAllHosts(httpsURLConnection);
            httpsURLConnection.setHostnameVerifier(DO_NOT_VARIFY);

            // 拼接请求头
            if (headers == null || headers.size() <= 0) {
                setDefaultHeader(httpsURLConnection);
            } else {
                setCustomizedHeader(httpsURLConnection, headers);
            }

            // 拼接请求体
            String parameterStr = getPostBody(bodyMap, submitType);

            byte[] writeBytes = parameterStr.getBytes();
            httpsURLConnection.setRequestProperty("Content-Length", String.valueOf(writeBytes.length));

            // 发起请求
            OutputStream outputStream = httpsURLConnection.getOutputStream();
            outputStream.write(writeBytes);
            outputStream.flush();
            outputStream.close();

            if (httpsURLConnection.getResponseCode() == HttpStatus.SC_OK || httpsURLConnection.getResponseCode() == HttpStatus.SC_CREATED) {
                inputStream = httpsURLConnection.getInputStream();
            } else {
                inputStream = httpsURLConnection.getErrorStream();
            }
            String contentEncoding = httpsURLConnection.getContentEncoding();
            if (contentEncoding != null && HttpConnectContant.RESPONSE_CODE_GZIP.equals(contentEncoding.trim().toLowerCase())) {
                gzipInputStream = new GZIPInputStream(inputStream);
                reader = new InputStreamReader(gzipInputStream);
            } else {
                reader = new InputStreamReader(inputStream);
            }

            StringBuilder sbd = new StringBuilder();
            char[] c = new char[1024];
            int len;
            while (0 < (len = reader.read(c))) {
                sbd.append(c, 0, len);
            }

            List<HeaderVo> headerList = Lists.newArrayList();
            Map<String, List<String>> responseHeaderFields = httpsURLConnection.getHeaderFields();
            if (responseHeaderFields != null && responseHeaderFields.size() > 0) {
                responseHeaderFields.forEach((key, value) -> headerList.add(new HeaderVo(key, JsonUtil.objectToJson(value))));
            }

            responseObj.setStatusCode(httpsURLConnection.getResponseCode());
            responseObj.setContent(sbd.toString());
            responseObj.setResponseHeader(headerList);
            responseObj.setUserAgent(httpsURLConnection.getRequestProperty("user-agent"));

        } catch (IOException e) {
            e.printStackTrace();
            responseObj.setStatusCode(-1);
            responseObj.setReasonPhrase("Crawl Error : HttpsUrlConnection IOException .");
        } finally {
            try {
                if (reader != null) {
                    reader.close();
                }
                if (gzipInputStream != null) {
                    gzipInputStream.close();
                }
                if (inputStream != null) {
                    inputStream.close();
                }
                if (httpsURLConnection != null) {
                    httpsURLConnection.disconnect();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return responseObj;
    }

    /**
     * https POST方法
     */
    private static ResponseObj httpConnectionPost(URL requestUrl, String ip, Integer port, Map<String, String> headers, Map<String, String> bodyMap, String submitType) {
        Reader reader = null;
        GZIPInputStream gzipInputStream = null;
        InputStream inputStream = null;
        HttpURLConnection httpURLConnection = null;
        ResponseObj responseObj = new ResponseObj();
        try {
            httpURLConnection = (HttpURLConnection) getUrlConnection(requestUrl, ip, port);
            httpURLConnection.setRequestMethod(HttpConnectContant.POST);

            // 设置默认请求属性
            setDefaultProperties(httpURLConnection);
            httpURLConnection.setUseCaches(false);

            // 拼接请求头
            if (headers == null || headers.size() <= 0) {
                setDefaultHeader(httpURLConnection);
            } else {
                setCustomizedHeader(httpURLConnection, headers);
            }

            // 拼接请求体
            String parameterStr = getPostBody(bodyMap, submitType);

            byte[] writeBytes = parameterStr.getBytes();
            httpURLConnection.setRequestProperty("Content-Length", String.valueOf(writeBytes.length));

            // 发起请求
            OutputStream outputStream = httpURLConnection.getOutputStream();
            outputStream.write(writeBytes);
            outputStream.flush();
            outputStream.close();

            if (httpURLConnection.getResponseCode() == HttpStatus.SC_OK || httpURLConnection.getResponseCode() == HttpStatus.SC_CREATED) {
                inputStream = httpURLConnection.getInputStream();
            } else {
                inputStream = httpURLConnection.getErrorStream();
            }
            String contentEncoding = httpURLConnection.getContentEncoding();
            if (contentEncoding != null && HttpConnectContant.RESPONSE_CODE_GZIP.equals(contentEncoding.trim().toLowerCase())) {
                gzipInputStream = new GZIPInputStream(inputStream);
                reader = new InputStreamReader(gzipInputStream);
            } else {
                reader = new InputStreamReader(inputStream);
            }

            StringBuilder sbd = new StringBuilder();
            char[] c = new char[1024];
            int len;
            while (0 < (len = reader.read(c))) {
                sbd.append(c, 0, len);
            }

            List<HeaderVo> headerList = Lists.newArrayList();
            Map<String, List<String>> responseHeaderFields = httpURLConnection.getHeaderFields();
            if (responseHeaderFields != null && responseHeaderFields.size() > 0) {
                responseHeaderFields.forEach((key, value) -> headerList.add(new HeaderVo(key, JsonUtil.objectToJson(value))));
            }

            responseObj.setStatusCode(httpURLConnection.getResponseCode());
            responseObj.setContent(sbd.toString());
            responseObj.setResponseHeader(headerList);
            responseObj.setUserAgent(httpURLConnection.getRequestProperty("user-agent"));

        } catch (IOException e) {
            e.printStackTrace();
            responseObj.setStatusCode(-1);
            responseObj.setReasonPhrase("Crawl Error : HttpsUrlConnection IOException .");
        } finally {
            try {
                if (reader != null) {
                    reader.close();
                }
                if (gzipInputStream != null) {
                    gzipInputStream.close();
                }
                if (inputStream != null) {
                    inputStream.close();
                }
                if (httpURLConnection != null) {
                    httpURLConnection.disconnect();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return responseObj;
    }

    /**
     * 拼接 POST 请求 请求体
     */
    private static String getPostBody(Map<String, String> bodyMap, String submitType) {
        String parameterStr;
        StringBuilder sbd = new StringBuilder();
        if (bodyMap != null && bodyMap.size() > 0 && HttpConnectContant.POST_BODY_TYPE_FORMAT.equals(submitType)) {
            //todo 数组类型数据不合适,需要优化
            bodyMap.forEach((key, value) -> sbd.append(key).append("=").append(value).append("&"));
            parameterStr = sbd.toString();
        } else {
            parameterStr = JsonUtil.objectToJson(bodyMap);
        }
        if (StringUtils.isBlank(parameterStr)) {
            parameterStr = "";
        }
        return parameterStr;
    }

//region---------------------------------------设置头部信息-----------------------------------------------------

    /**
     * 先设置默认头部信息
     * 然后用新的头部信息覆盖默认信息
     */
    private static void setCustomizedHeader(URLConnection urlConnection, Map<String, String> headerMap) {
        setDefaultHeader(urlConnection);
        for (Map.Entry<String, String> entry : headerMap.entrySet()) {
            urlConnection.setRequestProperty(entry.getKey(), entry.getValue());
        }
    }

    /**
     * 设置默认头部信息
     */
    private static void setDefaultHeader(URLConnection urlConnection) {
        urlConnection.setRequestProperty("accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8");
        urlConnection.setRequestProperty("accept-encoding", "gzip, deflate, br");
        urlConnection.setRequestProperty("accept-language", "en-US,en;q=0.9,fr-FR;q=0.8,fr-CA;q=0.7,fr;q=0.6,de;q=0.5,zh-CN;q=0.4,zh;q=0.3,en-AU;q=0.2");
        urlConnection.setRequestProperty("cache-control", "max-age=0");
        urlConnection.setRequestProperty("user-agent", "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.79 Safari/537.36");
        urlConnection.setRequestProperty("connection", "keep-alive");
    }

    /**
     * 设置默认属性
     */
    private static void setDefaultProperties(URLConnection urlConnection) {
        urlConnection.setDoOutput(true);
        urlConnection.setDoInput(true);
        urlConnection.setConnectTimeout(HttpConnectContant.CONNECT_TIME_OUT_TIME);

        // 系统超时设置, 防止网络异常情况下, 可能会导致程序僵死而不继续往下执行
        System.setProperty("sun.net.client.defaultConnectionTimeOut", String.valueOf(HttpConnectContant.CONNECT_TIME_OUT_TIME));
        System.setProperty("sun.net.client.defaultReadTimeout", String.valueOf(HttpConnectContant.CONNECT_TIME_OUT_TIME));
    }

    /**
     * 打开连接,获取连接对象
     */
    private static URLConnection getUrlConnection(URL requestUrl, String ip, Integer port) throws IOException {
        Proxy proxy = null;
        if (StringUtils.isNotBlank(ip) && port != null && port > 0) {
            proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(ip, port));
        }
        if (proxy == null) {
            return requestUrl.openConnection();
        }
        return requestUrl.openConnection(proxy);
    }


//endregion-------------------------------------------------------------------------------------------------------------

//region ------------------------------------- 绕过 https 验证 -----------------------------------------------------------
    /**
     * 覆盖java默认的证书验证
     */
    private static final TrustManager[] TRUST_ALL_CERTS = new TrustManager[]{
            new X509TrustManager() {
                @Override
                public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {

                }

                @Override
                public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {

                }

                @Override
                public X509Certificate[] getAcceptedIssuers() {
                    return new X509Certificate[]{};
                }
            }
    };

    /**
     * 设置不验证主机
     */
    private static final HostnameVerifier DO_NOT_VARIFY = new HostnameVerifier() {
        @Override
        public boolean verify(String s, SSLSession sslSession) {
            return true;
        }
    };

    /**
     * 信任所有的链接
     */
    private static SSLSocketFactory trustAllHosts(HttpsURLConnection connection) {
        SSLSocketFactory sslSocketFactory = connection.getSSLSocketFactory();
        try {
            SSLContext tls = SSLContext.getInstance("TLS");
            tls.init(null, TRUST_ALL_CERTS, new SecureRandom());
            SSLSocketFactory socketFactory = tls.getSocketFactory();
            connection.setSSLSocketFactory(socketFactory);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (KeyManagementException e) {
            e.printStackTrace();
        }
        return sslSocketFactory;
    }
// endregion -----------------------------------------------------------------------------------------------------------


}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值