基于线程池http请求示例

434 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第5天,点击查看活动详情

1、前言

之前在一个项目中,发现有一些功能需要通过http请求三方接口。然后发现里面自定义的的http工具类,每次请求都会新建一个HttpClient对象,造成了非常严重的资源浪费。一到线上并发量大的时候,功能就会出现一些卡顿情况。这里引入了线程池对其改造,同时将原有工具类废弃掉。

2、废弃旧的工具类

/**
 * 因 HttpRequestUtil 中未使用线程池,影响性能,已弃用,改用HttpRequestPoolUtil
 * @deprecated Use
 * {@link HttpRequestPoolUtil},
 *
 */
@Deprecated
public class HttpRequestUtil {

}

将@Deprecated写到类上就可实现对类的废弃,同时还要写清楚废弃原因并指明新的工具类。再使用旧的工具类时就会出现如下的提示效果:

image.png

3、改造Http工具类,引入线程池

/**
 * httpclient连接池工具类
 * **/
public class HttpRequestPoolUtil {
    private static PoolingHttpClientConnectionManager cm;
    private static String EMPTY_STR = "";
    private static String UTF_8 = "UTF-8";
    private static RequestConfig requestConfig;

    private static void init() {
        if (cm == null) {
            synchronized(HttpRequestPoolUtil.class) {
                if (cm == null) {
                    cm = new PoolingHttpClientConnectionManager();
                    // 整个连接池最大连接数
                    cm.setMaxTotal(1000);
                    // 每路由最大连接数,默认值是2
                    cm.setDefaultMaxPerRoute(200);
                }
            }
        }
    }

    /**
     * 请求配置文件
     */
    private static RequestConfig createRequestConfig() {
        if (requestConfig == null) {

            try {
                requestConfig = RequestConfig.custom()
                        .setConnectTimeout(Integer.parseInt("1000"))// 设置客户端发起TCP连接请求的超时时间,单位毫秒
                        .setConnectionRequestTimeout(Integer.parseInt("3000")) // 设置客户端从连接池获取链接的超时时间
                        .setSocketTimeout(Integer.parseInt("5000"))// 设置客户端等待服务端返回数据的超时时间,单位毫秒。
                        .build();
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        return requestConfig;
    }

    /**
     * 通过连接池获取HttpClient
     *
     * @return
     */
    private static CloseableHttpClient getHttpClient() {
        init();
        return HttpClients.custom().setConnectionManager(cm).build();
    }

    /**
     * @param url
     * @return
     */
    public static String httpGetRequest(String url) {
        HttpGet httpGet = new HttpGet(url);
        httpGet.setConfig(createRequestConfig());
        return getResult(httpGet);
    }

    public static String httpGetRequest(String url, Map<String, Object> params) throws URISyntaxException {
        URIBuilder ub = new URIBuilder(url);
        ArrayList<NameValuePair> pairs = covertParams2NVPS(params);
        ub.setParameters(pairs);
        HttpGet httpGet = new HttpGet(ub.build());
        httpGet.setConfig(createRequestConfig());
        return getResult(httpGet);
    }

    public static String httpGetRequest(String url, Map<String, Object> headers, Map<String, Object> params)
            throws URISyntaxException {
        URIBuilder ub = new URIBuilder();
        ub.setPath(url);
        ArrayList<NameValuePair> pairs = covertParams2NVPS(params);
        ub.setParameters(pairs);
        HttpGet httpGet = new HttpGet(ub.build());
        httpGet.setConfig(createRequestConfig());
        for (Map.Entry<String, Object> param : headers.entrySet()) {
            httpGet.addHeader(param.getKey(), String.valueOf(param.getValue()));
        }
        return getResult(httpGet);
    }

    public static String httpPostRequest(String url) {
        HttpPost httpPost = new HttpPost(url);
        httpPost.setConfig(createRequestConfig());
        return getResult(httpPost);
    }

    public static String httpPostRequest(String url,String json) {
        HttpPost httpPost = new HttpPost(url);
        StringEntity entity = new StringEntity(json,"utf-8");//解决中文乱码问题
        entity.setContentEncoding("UTF-8");
        entity.setContentType("application/json");
        httpPost.setEntity(entity);
        httpPost.setConfig(createRequestConfig());
        return getResult(httpPost);
    }

    public static String httpPostRawJsonRequest(String url, Map<String, Object> headers, Map<String, Object> params) throws UnsupportedEncodingException {
        HttpPost httpPost = new HttpPost(url);
        String jsonStr = JSON.toJSONString(params);
        //设置请求体参数
        StringEntity entity = new StringEntity(jsonStr,"utf-8");
        httpPost.setEntity(entity);
        httpPost.setConfig(createRequestConfig());
        for (Map.Entry<String, Object> param : headers.entrySet()) {
            httpPost.addHeader(param.getKey(), String.valueOf(param.getValue()));
        }
        return getResult(httpPost);
    }

    public static String httpPostRequest(String url, Map<String, Object> params) throws UnsupportedEncodingException {
        HttpPost httpPost = new HttpPost(url);
        ArrayList<NameValuePair> pairs = covertParams2NVPS(params);
        httpPost.setEntity(new UrlEncodedFormEntity(pairs, UTF_8));
        httpPost.setConfig(createRequestConfig());
        return getResult(httpPost);
    }

    public static String httpPostRequest(String url, Map<String, Object> headers, Map<String, Object> params)
            throws UnsupportedEncodingException {
        HttpPost httpPost = new HttpPost(url);
        httpPost.setConfig(createRequestConfig());
        for (Map.Entry<String, Object> param : headers.entrySet()) {
            httpPost.addHeader(param.getKey(), String.valueOf(param.getValue()));
        }
        ArrayList<NameValuePair> pairs = covertParams2NVPS(params);
        httpPost.setEntity(new UrlEncodedFormEntity(pairs, UTF_8));

        return getResult(httpPost);
    }

    private static ArrayList<NameValuePair> covertParams2NVPS(Map<String, Object> params) {
        ArrayList<NameValuePair> pairs = new ArrayList<NameValuePair>();
        for (Map.Entry<String, Object> param : params.entrySet()) {
            pairs.add(new BasicNameValuePair(param.getKey(), String.valueOf(param.getValue())));
        }
        return pairs;
    }


    public static String doPost(String url, Map<String, Object> map,Map<String, String> header) throws Exception {
        // 声明httpPost请求
        HttpPost httpPost = new HttpPost(url);
        // 加入配置信息
        httpPost.setConfig(createRequestConfig());
        //设置Header
        for (Map.Entry<String, String> cmap :header.entrySet()){
            httpPost.addHeader(cmap.getKey(),cmap.getValue());
        }
        httpPost.addHeader("Content-Type", "application/json;charset=utf-8");

        // 判断map是否为空,不为空则进行遍历,封装from表单对象
        if (map != null) {
            //body里添加参数,使用这种方式
            JSONObject jsonObject = new JSONObject(map);
            // 把表单放到post里
            httpPost.setEntity(new StringEntity(jsonObject.toJSONString()));
        }
        // 发起请求
        return getResult(httpPost);
    }


    /**
     * 处理Http请求
     */
    private static String getResult(HttpRequestBase request) {
        // CloseableHttpClient httpClient = HttpClients.createDefault();
        CloseableHttpClient httpClient = getHttpClient();
        CloseableHttpResponse response = null;
        String result ="";
        try {
            response = httpClient.execute(request);
            // response.getStatusLine().getStatusCode();
            HttpEntity entity = response.getEntity();
            if (entity != null) {
                // long len = entity.getContentLength();// -1 表示长度未知
                result = EntityUtils.toString(entity);
                //response.close();
                // httpClient.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //5.回收链接到连接池
            if (null != response) {
                try {
                    EntityUtils.consume(response.getEntity());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            return result;
        }
    }
}

好了、本期就先介绍到这里,有什么需要交流的,大家可以随时私信我。😊