httpclient请求

引入maven依赖

<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
    <version>4.1.4</version>
</dependency>
<dependency>
    <groupId>org.apache.httpcomponents</groupId>    
     <artifactId>httpcore</artifactId>
    <version>4.4.12</version>
</dependency>
 <dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpasyncclient</artifactId>
    <version>4.4.12</version>
</dependency>
 <dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpcore-nio</artifactId>
    <version>4.4.12</version>
</dependency>
 <dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpmime</artifactId>
    <version>4.5.9</version>
</dependency>

 

import com.alibaba.fastjson.TypeReference;
import com.alibaba.fastjson.util.IOUtils;
import com.google.common.base.Joiner;
import com.google.common.base.Stopwatch;
import com.google.common.collect.Maps;
import com.meituan.mtrace.http.HttpAsyncClients;
import com.meituan.mtrace.http.HttpClients;
import com.sankuai.meituan.common.json.JSONUtil;
import com.sankuai.shangou.empower.uwms.common.utils.FastJsonUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.MapUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
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.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.HttpClientConnectionManager;
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.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.impl.nio.client.CloseableHttpAsyncClient;
import org.apache.http.impl.nio.conn.PoolingNHttpClientConnectionManager;
import org.apache.http.impl.nio.reactor.DefaultConnectingIOReactor;
import org.apache.http.impl.nio.reactor.IOReactorConfig;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.nio.reactor.ConnectingIOReactor;
import org.apache.http.nio.reactor.IOReactorException;
import org.apache.http.protocol.HttpContext;
import org.apache.http.util.EntityUtils;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class HttpClientUtil {

    private static final String CHARSET_UTF8 = "UTF-8";
    private static final Pattern HTTP_PATTERN = Pattern.compile("^(https?|ftp|file)://[-a-zA-Z0-9+&@#/%?=~_|!:,.;]*[-a-zA-Z0-9+&@#/%=~_|]");
    private static volatile CloseableHttpClient httpClient;
    private static volatile CloseableHttpAsyncClient httpAsyncClient;

    // 默认socket连接超时时间
    private static final int DEFAULT_SOCKET_TIMEOUT = 10 * 1000;
    // 默认HTTP连接超时时间
    private static final int DEFAULT_CONNECT_TIMEOUT = 5 * 1000;

    /**
     * 默认请求头
     */
    private static final Map<String, String> DEFAULT_HEADER = Maps.newHashMap();

    static {
        // DEFAULT_HEADER.put("Content-Type", "application/json; charset=UTF-8");
    }

    private HttpClientUtil() {
    }

    /**
     * 启动时初始化httpClient及连接池的连接数
     */
    public static CloseableHttpClient getHttpClient() {
        if (null == httpClient) {
            synchronized (HttpClientUtil.class) {
                if (null == httpClient) {
                    log.info("HttpClientUtil.getHttpClient, 初始化httpClient");
                    httpClient = HttpClients.custom().setConnectionManager(
                            buildConnectionManager()).setRetryHandler(buildRetryHandler()).build();
                }
            }
        }
        return httpClient;
    }

    /**
     * 启动时初始化httpAsyncClient及连接池的连接数
     */
    public static CloseableHttpAsyncClient getHttpAsyncClient() {
        if (null == httpAsyncClient) {
            synchronized (HttpClientUtil.class) {
                if (null == httpAsyncClient) {
                    httpAsyncClient = HttpAsyncClients.custom()
                            .setConnectionManager(buildPoolConnectionManager())
                            .setDefaultRequestConfig(RequestConfig.custom().setSocketTimeout(DEFAULT_SOCKET_TIMEOUT)
                                    .setConnectTimeout(DEFAULT_CONNECT_TIMEOUT).build()).build();
                }
            }
        }
        return httpAsyncClient;
    }


    /**
     * 执行post请求获取响应字符串
     *
     * @param url            请求url
     * @param connectTimeOut 连接超时时间
     * @param socketTimeOut  socket超时时间
     * @param params         post请求参数
     * @return 响应字符串
     */
    public static String post(String url, int connectTimeOut, int socketTimeOut, Map<String, Object> params) {
        return post(url, connectTimeOut, socketTimeOut, params, DEFAULT_HEADER);
    }

    public static String post(String url, int connectTimeOut, int socketTimeOut, Map<String, Object> params,
                              Map<String, String> headers) {
        // 构建httppost请求配置、实体、请求头
        HttpPost httpPost = new HttpPost(url);
        setPostConfig(httpPost, connectTimeOut, socketTimeOut);
        setPostEntity(httpPost, params);
        setPostHeader(httpPost, headers);
        // 发送post请求
        CloseableHttpResponse response = null;
        String result = "";
        Stopwatch stopwatch = Stopwatch.createStarted();
        try {
            response = getHttpClient().execute(httpPost);
            // 返回不为成功时直接返回null
            if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
                log.error("HttpClientUtil.post, 发送POST请求获取响应, httpcode:{}, url:{}, connectTimeOut:{}, socketTimeOut:{}, params:{}, headers:{}",
                        response.getStatusLine().getStatusCode(), url, connectTimeOut, socketTimeOut, params, headers);
                return null;
            }
            HttpEntity entity = response.getEntity();
            result = EntityUtils.toString(entity, CHARSET_UTF8);
            if (MccConfigUtil.getCanLogHttpRequestResult()) {
                try {
                    log.info("url = {} param = {}, result = {} header = {}", url, JSONUtil.toJSONString(params), result);
                } catch (Exception e) {
                    log.error("url = {}", url, e);
                }
            }
            return result;
        } catch (Exception e) {
            log.error("HttpClientUtil.post, 执行POST请求失败, url:{}, connectTimeOut:{}, socketTimeOut:{}, params:{}, headers:{}, exception",
                    url, connectTimeOut, socketTimeOut, params, headers, e);
            return null;
        } finally {
            // 关闭响应
            IOUtils.close(response);
            log.info("HttpClientUtil.post, 发送POST请求的url:{}, cost={}", url, stopwatch.elapsed(TimeUnit.MILLISECONDS));
        }
    }

    public static String get(String url, int connectTimeOut, int socketTimeOut, Map<String, String> params) {
        return getWithHeader(url, connectTimeOut, socketTimeOut, params, null);
    }

    /**
     * 执行get请求获取响应字符串
     *
     * @param url 请求url
     * @return 响应字符串
     */
    public static String getWithHeader(String url, int connectTimeOut, int socketTimeOut, Map<String, String> params,
                                       Map<String, String> header) {
        String result = "";
        CloseableHttpResponse response = null;
        Stopwatch stopwatch = Stopwatch.createStarted();
        try {
            HttpGet httpGet = new HttpGet(assembleUrl(url, params));
            setGetConfig(httpGet, connectTimeOut, socketTimeOut);
            if (header != null) {
                for (Map.Entry<String, String> entry : header.entrySet()) {
                    httpGet.setHeader(entry.getKey(), entry.getValue());
                }
            }
            response = getHttpClient().execute(httpGet);

            // 返回不为成功时直接返回null
            if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
                log.error("HttpClientUtil.get, 发送GET请求获取响应状态, httpcode={}, url:{}, connectTimeOut:{}, socketTimeOut:{}, params:{}",
                        response.getStatusLine().getStatusCode(), assembleUrl(url, params), connectTimeOut, socketTimeOut, params);
                return null;
            }
            HttpEntity entity = response.getEntity();
            result = EntityUtils.toString(entity, CHARSET_UTF8);
            return result;
        } catch (Exception e) {
            log.error("HttpClientUtil.get, 执行GET请求失败, url:{}, connectTimeOut:{}, socketTimeOut:{}, params:{}, exception={}",
                    assembleUrl(url, params), connectTimeOut, socketTimeOut, FastJsonUtils.toJSONString(params), e);
            return null;
        } finally {
            // 关闭响应
            IOUtils.close(response);
            if (MccConfigUtil.getCanLogHttpRequestResult()) {
                log.info("HttpClientUtil.get, 发送GET请求的, url:{}, param = {} result = {} cost:{}, ",
                        url,
                        FastJsonUtils.toJSONString(params),
                        result,
                        stopwatch.elapsed(TimeUnit.MILLISECONDS));
            }
        }
    }

    /**
     * 拼接GET请求参数
     */
    public static String assembleUrl(String url, Map<String, String> params) {
        //校验参数
        if (MapUtils.isEmpty(params)) {
            return url;
        }
        //校验url的准确性
        Matcher matcher = HTTP_PATTERN.matcher(url);
        if (!matcher.matches()) {
            throw new IllegalArgumentException("illegal argument with url = " + url);
        }
        StringBuilder resultUrl = new StringBuilder(url);
        try {
            if (!url.contains("?")) {
                resultUrl.append("?");
            } else {
                if (!"?".endsWith(url)) {
                    resultUrl.append("&");
                }
            }
            return resultUrl.append(Joiner.on("&").withKeyValueSeparator("=").join(params)).toString();
        } catch (Exception e) {
            log.error("HttpClientUtil.assembleUrl, 拼接url异常, url:{}, exception={}", url, e);
        }
        return resultUrl.toString();
    }

    /**
     * 设置post请求超时时间
     *
     * @param httpPost       httppost
     * @param connectTimeOut 连接超时时间
     * @param socketTimeOut  socket读写超时时间
     */
    private static void setPostConfig(HttpPost httpPost, int connectTimeOut, int socketTimeOut) {
        RequestConfig requestConfig = RequestConfig.custom()
                .setConnectionRequestTimeout(connectTimeOut)
                .setConnectTimeout(connectTimeOut)
                .setSocketTimeout(socketTimeOut).build();
        httpPost.setConfig(requestConfig);
    }

    /**
     * 设置get请求超时时间
     *
     * @param httpGet        httpget
     * @param connectTimeOut 连接超时时间
     * @param socketTimeOut  socket读写超时时间
     */
    private static void setGetConfig(HttpGet httpGet, int connectTimeOut, int socketTimeOut) {
        RequestConfig requestConfig = RequestConfig.custom()
                .setConnectionRequestTimeout(connectTimeOut)
                .setConnectTimeout(connectTimeOut)
                .setSocketTimeout(socketTimeOut).build();
        httpGet.setConfig(requestConfig);
    }

    /**
     * 设置post请求实体
     *
     * @param httpPost httppost
     * @param params   实体参数
     */
    private static void setPostEntity(HttpPost httpPost, Map<String, Object> params) {
        // 将map转化成httppost的实体
        List<NameValuePair> nvps = new ArrayList<>();
        for (Map.Entry<String, Object> entry : params.entrySet()) {
            nvps.add(new BasicNameValuePair(entry.getKey(), String.valueOf(entry.getValue())));
        }
        try {
            httpPost.setEntity(new UrlEncodedFormEntity(nvps, CHARSET_UTF8));
        } catch (UnsupportedEncodingException e) {
            log.error("HttpClientUtil.setPostEntity, 实体转化成UTF-8格式出错, httpPost:{}, params:{}, exception={}", httpPost, params, e);
        }
    }

    /**
     * 设置post请求头
     *
     * @param httpPost httppost
     * @param headers  请求头
     */
    private static void setPostHeader(HttpPost httpPost, Map<String, String> headers) {
        for (Map.Entry<String, String> entry : headers.entrySet()) {
            httpPost.setHeader(entry.getKey(), entry.getValue());
        }
    }

    /**
     * 构建http连接管理器
     *
     * @return 连接管理器
     */
    private static HttpClientConnectionManager buildConnectionManager() {
        ConnectionSocketFactory plainsf = PlainConnectionSocketFactory.getSocketFactory();
        LayeredConnectionSocketFactory sslsf = SSLConnectionSocketFactory.getSocketFactory();
        Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
                .register("http", plainsf).register("https", sslsf).build();
        PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager(registry);
        // 将最大连接数增加
        cm.setMaxTotal(MccConfigUtil.getHttpMaxTotal());
        // 将每个路由基础的连接增加
        cm.setDefaultMaxPerRoute(MccConfigUtil.getHttpMaxPerRoute());
        return cm;
    }

    /**
     * 构建http异步连接管理器
     *
     * @return
     */
    private static PoolingNHttpClientConnectionManager buildPoolConnectionManager() {
        try {
            IOReactorConfig ioReactorConfig = IOReactorConfig.custom().setIoThreadCount(MccConfigUtil.getHttpAsyncIoThreadCount()).build();
            ConnectingIOReactor ioReactor = new DefaultConnectingIOReactor(ioReactorConfig);
            PoolingNHttpClientConnectionManager cm = new PoolingNHttpClientConnectionManager(ioReactor);
            cm.setMaxTotal(MccConfigUtil.getHttpAsyncMaxTotal());
            cm.setDefaultMaxPerRoute(MccConfigUtil.getHttpAsyncMaxPerRoute());
            return cm;
        } catch (IOReactorException e) {
            log.error("HttpClientUtil.buildPoolConnectionManager, 构建http异步连接管理器异常, exception={}", e);
        }
        return null;
    }

    /**
     * 构建重试次数的handler
     *
     * @return handler
     */
    private static HttpRequestRetryHandler buildRetryHandler() {
        return (IOException exception, int executionCount, HttpContext context) -> {
            // 校验重试次数
            if (executionCount >= MccConfigUtil.getHttpRetryTimes()) {
                return false;
            }
            return true;
        };
    }

    public static <T> T postJson(String url, int connectTimeOut, int socketTimeOut, Map<String, Object> params,
                                 TypeReference<T> typeReference) {

        // 构建httppost请求配置、实体、请求头
        HttpPost httpPost = new HttpPost(url);
        setPostConfig(httpPost, connectTimeOut, socketTimeOut);
        setJsonData(httpPost, params);
        // 发送post请求
        CloseableHttpResponse response = null;
        String result = "";
        Stopwatch stopwatch = Stopwatch.createStarted();
        try {
            response = getHttpClient().execute(httpPost);
            // 返回不为成功时直接返回null
            if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
                log.error("HttpClientUtil.post, 发送POST请求获取响应, httpcode:{}, url:{}, connectTimeOut:{}, socketTimeOut:{}, params:{}",
                        response.getStatusLine().getStatusCode(), url, connectTimeOut, socketTimeOut, params);
                return null;
            }
            HttpEntity entity = response.getEntity();
            result = EntityUtils.toString(entity, CHARSET_UTF8);
            return FastJsonUtils.parseObject(result, typeReference);
        } catch (Exception e) {
            log.error("HttpClientUtil.post, 执行POST请求失败, url:{}, connectTimeOut:{}, socketTimeOut:{}, params:{}, exception={}",
                    url, connectTimeOut, socketTimeOut, params, e);
            return null;
        } finally {
            // 关闭响应
            IOUtils.close(response);
            log.info("HttpClientUtil.post, 发送POST请求的url:{}, param = {} , result = {}cost={}", url,
                    FastJsonUtils.toJSONString(params),
                    result,
                    stopwatch.elapsed(TimeUnit.MILLISECONDS));
        }
    }

    private static void setJsonData(HttpPost httpPost, Map<String, Object> params) {
        StringEntity entity = new StringEntity(FastJsonUtils.toJSONString(params),
                "utf-8");//解决中文乱码问题
        entity.setContentEncoding("UTF-8");
        entity.setContentType("application/json");
        httpPost.setEntity(entity);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值