zoukankan      html  css  js  c++  java
  • HttpClient工具类(使用连接池)

    HttpClient工具类(使用连接池)

    HttpClient简介

    (~~~~~)HTTP 协议可能是现在 Internet 上使用得最多、最重要的协议了,越来越多的 Java 应用程序需要直接通过 HTTP 协议来访问网络资源。虽然在 JDK 的 java net包中已经提供了访问 HTTP 协议的基本功能,但是对于大部分应用程序来说,JDK 库本身提供的功能还不够丰富和灵活。HttpClient 是 Apache Jakarta Common 下的子项目,用来提供高效的、最新的、功能丰富的支持 HTTP 协议的客户端编程工具包,并且它支持 HTTP 协议最新的版本和建议。

    (~~~~~)HTTP和浏览器有点像,但却不是浏览器。很多人觉得既然HttpClient是一个HTTP客户端编程工具,很多人把他当做浏览器来理解,但是其实HttpClient不是浏览器,它是一个HTTP通信库,因此它只提供一个通用浏览器应用程序所期望的功能子集,最根本的区别是HttpClient中没有用户界面,浏览器需要一个渲染引擎来显示页面,并解释用户输入,例如鼠标点击显示页面上的某处,有一个布局引擎,计算如何显示HTML页面,包括级联样式表和图像。javascript解释器运行嵌入HTML页面或从HTML页面引用的javascript代码。来自用户界面的事件被传递到javascript解释器进行处理。除此之外,还有用于插件的接口,可以处理Applet,嵌入式媒体对象(如pdf文件,Quicktime电影和Flash动画)或ActiveX控件(可以执行任何操作)。HttpClient只能以编程的方式通过其API用于传输和接受HTTP消息

    HttpClient主要功能

    • 实现了所有 HTTP 的方法(GET、POST、PUT、HEAD、DELETE、HEAD、OPTIONS 等)
    • 支持 HTTPS 协议
    • 支持代理服务器(Nginx等)等
    • 支持自动(跳转)转向

    简单使用

    引入相关依赖

    <!-- https://mvnrepository.com/artifact/org.apache.httpcomponents/httpclient -->
    <dependency>
        <groupId>org.apache.httpcomponents</groupId>
        <artifactId>httpclient</artifactId>
        <version>4.5.5</version>
    </dependency>
    

    这里提醒一点:springboot中也已经整合有HttpClient依赖,也可以另外引入依赖

    单独发送Get请求

    /**
         * 向指定URL发送GET方法的请求
         *
         * @param url
         *            发送请求的URL
         * @param param
         *            请求参数,请求参数应该是 name1=value1&name2=value2 的形式。
         * @return URL 所代表远程资源的响应结果
         */
        public static String sendGet(String url, String param) {
            String result = "";
            BufferedReader in = null;
            try {
                String urlNameString = url + "?" + param;
                URL realUrl = new URL(urlNameString);
                // 打开和URL之间的连接
                URLConnection connection = realUrl.openConnection();
                // 设置通用的请求属性
                connection.setRequestProperty("accept", "*/*");
                connection.setRequestProperty("connection", "Keep-Alive");
                connection.setRequestProperty("user-agent",
                        "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
                // 建立实际的连接
                connection.connect();
                // 获取所有响应头字段
                Map<String, List<String>> map = connection.getHeaderFields();
                // 遍历所有的响应头字段
                for (String key : map.keySet()) {
                    System.out.println(key + "--->" + map.get(key));
                }
                // 定义 BufferedReader输入流来读取URL的响应
                in = new BufferedReader(new InputStreamReader(
                        connection.getInputStream()));
                String line;
                while ((line = in.readLine()) != null) {
                    result += line;
                }
            } catch (Exception e) {
                System.out.println("发送GET请求出现异常!" + e);
                e.printStackTrace();
            }
            // 使用finally块来关闭输入流
            finally {
                try {
                    if (in != null) {
                        in.close();
                    }
                } catch (Exception e2) {
                    e2.printStackTrace();
                }
            }
            return result;
        }
    

    单独发送Post请求


    post请求有两种方式传参,一种是普通参数,一种是对象参数

    /**
         * 向指定 URL 发送POST方法的请求
         *
         * @param url
         *            发送请求的 URL
         * @param param
         *            请求参数,请求参数应该是 name1=value1&name2=value2 的形式。
         * @return 所代表远程资源的响应结果
         */
        public static String sendPost(String url, String param) {
            PrintWriter out = null;
            BufferedReader in = null;
            String result = "";
            try {
                URL realUrl = new URL(url);
                // 打开和URL之间的连接
                URLConnection conn = realUrl.openConnection();
                // 设置通用的请求属性
                conn.setRequestProperty("accept", "*/*");
                conn.setRequestProperty("connection", "Keep-Alive");
                conn.setRequestProperty("user-agent",
                        "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
                // 发送POST请求必须设置如下两行
                conn.setDoOutput(true);
                conn.setDoInput(true);
                // 获取URLConnection对象对应的输出流
                out = new PrintWriter(conn.getOutputStream());
                // 发送请求参数
                out.print(param);
                // flush输出流的缓冲
                out.flush();
                // 定义BufferedReader输入流来读取URL的响应
                in = new BufferedReader(
                        new InputStreamReader(conn.getInputStream()));
                String line;
                while ((line = in.readLine()) != null) {
                    result += line;
                }
            } catch (Exception e) {
                System.out.println("发送 POST 请求出现异常!"+e);
                e.printStackTrace();
            }
            //使用finally块来关闭输出流、输入流
            finally{
                try{
                    if(out!=null){
                        out.close();
                    }
                    if(in!=null){
                        in.close();
                    }
                }
                catch(IOException ex){
                    ex.printStackTrace();
                }
            }
            return result;
        }
    

    使用HttpClient连接池,优化连接


    • 这里整合在springboot :2.2.6.RELEASE 版本
    package com.vx.music.http;
    
    import org.apache.http.HttpEntity;
    import org.apache.http.NameValuePair;
    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.entity.StringEntity;
    import org.apache.http.impl.client.CloseableHttpClient;
    import org.apache.http.impl.client.HttpClients;
    import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
    import org.apache.http.message.BasicNameValuePair;
    import org.apache.http.util.EntityUtils;
    
    import java.io.*;
    import java.net.URISyntaxException;
    import java.net.URL;
    import java.net.URLConnection;
    import java.util.ArrayList;
    import java.util.List;
    import java.util.Map;
    
    public class HttpClientApiUtils {
        private static PoolingHttpClientConnectionManager cm;
        private static String EMPTY_STR = "";
        private static String UTF_8 = "UTF-8";
    
        private static void init() {
            if (cm == null) {
                cm = new PoolingHttpClientConnectionManager();
                // 整个连接池最大连接数
                cm.setMaxTotal(100);
                // 每路由最大连接数,默认值是2
                cm.setDefaultMaxPerRoute(5);
            }
        }
    
        /**
         * 通过连接池获取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);
            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());
            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());
            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);
            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);
            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));
            return getResult(httpPost);
        }
    
        public static String httpPostRequest(String url, Map<String, Object> headers, Map<String, Object> params)
                throws UnsupportedEncodingException {
            HttpPost httpPost = new HttpPost(url);
            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;
        }
    
        /**
         * 处理Http请求
         */
        private static String getResult(HttpRequestBase request) {
            // CloseableHttpClient httpClient = HttpClients.createDefault();
            CloseableHttpClient httpClient = getHttpClient();
            try {
                CloseableHttpResponse response = httpClient.execute(request);
                // response.getStatusLine().getStatusCode();
                HttpEntity entity = response.getEntity();
                if (entity != null) {
                    // long len = entity.getContentLength();// -1 表示长度未知
                    String result = EntityUtils.toString(entity);
                    response.close();
                    // httpClient.close();
                    return result;
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            return EMPTY_STR;
        }
    }
    

    HttpClient4.X发送Get请求的参数拼接

    使用httpClient发送get请求时,请求参数可以以?key=val&key1=val1的拼接到url后面。
    但是请求参数较多时,这种方法比较麻烦,也不太优雅;研究了一下发现HttpClient4.X本身
    是支持处理参数的。

    1. 使用 URIBuilder来构建请求URI

    import com.google.common.collect.Lists;
    import org.apache.http.Consts;
    import org.apache.http.HttpEntity;
    import org.apache.http.HttpStatus;
    import org.apache.http.NameValuePair;
    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.utils.URIBuilder;
    import org.apache.http.impl.client.CloseableHttpClient;
    import org.apache.http.impl.client.HttpClients;
    import org.apache.http.message.BasicNameValuePair;
    import org.apache.http.util.EntityUtils;
    
        private HttpGet buildHttpGet(String url, Map<String, String> para)
                throws URISyntaxException {
            URIBuilder builder = new URIBuilder(url);
            Set<String> set = para.keySet();
            for(String key: set){
                builder.setParameter(key, para.get(key));
            }
            HttpGet request = new HttpGet(builder.build());
            RequestConfig requestConfig = RequestConfig.custom()
                    .setSocketTimeout(6000)
                    .setConnectTimeout(6000)
                    .setConnectionRequestTimeout(6000).build();
            request.setConfig(requestConfig);
            System.out.println(request.getURI().toString());
            return request;
        }
    

    2. 使用 NameValuePair 来拼接URI

    List<NameValuePair> params = Lists.newArrayList();
    params.add(new BasicNameValuePair("cityEname", "henan"));
    String str = "";
    //转换为键值对
    str = EntityUtils.toString(new UrlEncodedFormEntity(params, Consts.UTF_8));
    System.out.println(str);
    HttpGet httpGet = new HttpGet(url + "?" + str);
    

    3. 根据 HttpGet反向获取键值对列表

    HttpGet request = new HttpGet("http://example.com/?var=1&var=2");
    URIBuilder newBuilder = new URIBuilder(request.getURI());
    //获取键值对列表
    List<NameValuePair> params = newBuilder.getQueryParams();
    //转换为键值对字符串
    String str = EntityUtils.toString(new UrlEncodedFormEntity(params, Consts.UTF_8));
    

    其它

    其它更多其它详细使用:

    https://github.com/Arronlong/httpclientutil
    
  • 相关阅读:
    React 源码剖析系列 - 生命周期的管理艺术
    大数据浪潮下的前端工程师
    win7 秘钥
    Immutable 详解及 React 中实践
    js 设置日期函数
    node 一站式 学习 教程
    Python_如何定义带参数的装饰器?
    Python-装饰器中保留被装饰函数元数据
    Python-用装饰器实现递归剪枝
    Python-通过实例方法调用-统一接口的实现-getter methodcaller
  • 原文地址:https://www.cnblogs.com/MrYuChen-Blog/p/14311553.html
Copyright © 2011-2022 走看看