编程随笔-SpringBoot | 28.用HttpClient实现在java端发送请求(附完整工具包代码)

0.参考文章

HttpClient详细使用示例

这位作者写的这篇文章非常好,各个环节写得非常详细。我在这篇文章的基础之上对代码结构进行了微调,使其看起来更加方便理解,并将在文末贴出完整的工具包代码,且后续会持续维护工具包。

1.概述

1.1.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就像是一个用于发送请求的客户端,在定义httpClient后,由编程人员自定义请求的配置,随后调用httpClient.execute()执行请求的发送并接收响应,最后再关闭httpClient以释放资源。

1.2.httpClient使用的大致流程

  1. 创建httpClient(http客户端)
  2. 处理参数(param参数转换成拼接到url上的字符串,body参数转换成json)
  3. 创建请求,依照各种参数对其配置(GET、POST)
  4. 声明响应模型response
  5. 发送请求,将响应赋值给响应模型,转换成json格式并返回
  6. 关闭httpClient和response,释放资源

1.3.MAVEN依赖

引入httpClient和httpmime依赖

<!-- httpClient -->
<dependency>
	<groupId>org.apache.httpcomponents</groupId>
	<artifactId>httpclient</artifactId>
	<version>4.3.6</version>
</dependency>
<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpmime</artifactId>
    <version>4.5</version>
</dependency>

引入fastJson依赖(处理响应)

<dependency>
	<groupId>com.alibaba</groupId>
	<artifactId>fastjson</artifactId>
	<version>1.2.3</version>
</dependency>

2.使用示例

创建HttpClientUtil类,声明private的静态变量requestConfig。

该变量的作用是对请求进行进一步配置。

image-20211110121559786

定义方法beforeInit(),在其上添加注解@PostConstruct

该方法用于对上述声明的变量requestConfig进行初始化,而@PostConstruct注解会使得该方法在服务器加载时被执行。

image-20211110122146115

beforeInit()代码如下:

@PostConstruct
public void beforeInit() {
    // 配置信息
    HttpClientUtil.requestConfig = RequestConfig.custom()
        // 设置连接超时时间(单位毫秒)
        .setConnectTimeout(5000)
        // 设置请求超时时间(单位毫秒)
        .setConnectionRequestTimeout(5000)
        // socket读写超时时间(单位毫秒)
        .setSocketTimeout(5000)
        // 设置是否允许重定向(默认为true)
        .setRedirectsEnabled(true).build();
}

2.1.无参GET请求

/**
	 * 01. 无参GET请求
	 *
	 * @param url
	 * @return
	 */
public static String get(String url) throws IOException {
    //1. 获得Http客户端
    CloseableHttpClient httpClient = HttpClientBuilder.create().build();

    //2. 创建GET请求
    HttpGet httpGet = new HttpGet(url);
    httpGet.setConfig(requestConfig);

    //3. 声明响应模型
    CloseableHttpResponse response = null;

    //4. 发送请求
    try {
        //4-1. 由客户端执行(发送)Get请求
        response = httpClient.execute(httpGet);
        //4-2. 从响应模型中获取响应实体
        HttpEntity responseEntity = response.getEntity();
        //4-3. 将响应实体以UTF-8编码解析成JSON并返回
        return EntityUtils.toString(responseEntity, "utf-8");
    } catch (Exception e) {
        throw e;
    } finally {
        try {
            // 释放资源
            if (httpClient != null) {
                httpClient.close();
            }
            if (response != null) {
                response.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

2.2.有参GET请求:param参数

param参数是指:将参数拼接到url上,就像这样:

image-20211110122931258

(上述是postMan的界面,这里只是作为演示)

/**
	 * 02. 有参GET请求
	 *
	 * @param url
	 * @param paramMap
	 * @return
	 * @throws IOException
	 */
public static String getWithParams(String url, Map<String, String> paramMap) throws IOException {
    //1. 获得Http客户端
    CloseableHttpClient httpClient = HttpClientBuilder.create().build();

    //2. 处理参数
    StringBuilder sb = new StringBuilder();
    int paramCount = 0;
    if(paramMap != null){
        paramCount = paramMap.size();
    }
    // 至少有一个参数时,循环拼接
    if (paramCount != 0) {
        // 先拼接"?"
        sb.append("?");
        // 遍历Key和value
        int pointer = 0;
        for (Map.Entry<String, String> entry : paramMap.entrySet()) {
            String key = entry.getKey();
            String value = (String) entry.getValue();
            //拼接数据
            sb.append(key).append("=").append(value);
            if (pointer != paramCount - 1) {
                sb.append("&");
                pointer++;
            }
        }
    }

    //3. 创建GET请求
    HttpGet httpGet = new HttpGet(url + sb.toString());
    httpGet.setConfig(requestConfig);

    //4. 声明响应模型
    CloseableHttpResponse response = null;

    //5. 发送请求
    try {
        //5-1. 由客户端执行(发送)Get请求
        response = httpClient.execute(httpGet);
        //5-2. 从响应模型中获取响应实体
        HttpEntity responseEntity = response.getEntity();
        //5-3. 将响应实体以UTF-8编码解析成JSON并返回
        return EntityUtils.toString(responseEntity, "utf-8");
    } catch (Exception e) {
        throw e;
    } finally {
        try {
            // 释放资源
            if (httpClient != null) {
                httpClient.close();
            }
            if (response != null) {
                response.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

2.3.无参POST请求

无参POST请求与无参GET请求几乎一致,只需要将HttpGet换成HttpPost即可

/**
	 * 03. 无参POST请求
	 *
	 * @param url
	 * @return
	 */
public static String post(String url) throws IOException {
    //1. 获得Http客户端
    CloseableHttpClient httpClient = HttpClientBuilder.create().build();

    //2. 创建POST请求
    HttpPost httpPost = new HttpPost(url);
    httpPost.setConfig(requestConfig);

    //3. 声明响应模型
    CloseableHttpResponse response = null;

    //4. 发送请求
    try {
        //4-1. 由客户端执行(发送)Get请求
        response = httpClient.execute(httpPost);
        //4-2. 从响应模型中获取响应实体
        HttpEntity responseEntity = response.getEntity();
        //4-3. 将响应实体以UTF-8编码解析成JSON并返回
        return EntityUtils.toString(responseEntity, "utf-8");
    } catch (Exception e) {
        throw e;
    } finally {
        try {
            // 释放资源
            if (httpClient != null) {
                httpClient.close();
            }
            if (response != null) {
                response.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

2.4.有参POST请求:param参数

POST请求中加入param参数和GET请求的方式是一样的,都是在url上拼接参数。

/**
	 * 04. 参数在params的POST请求
	 *
	 * @param url
	 * @param paramMap
	 * @return
	 * @throws IOException
	 */
public static String postWithParams(String url, Map<String, String> paramMap) throws IOException {
    //1. 获得Http客户端
    CloseableHttpClient httpClient = HttpClientBuilder.create().build();

    //2. 处理参数
    StringBuilder sb = new StringBuilder();
    int paramCount = 0;
    if(paramMap != null){
        paramCount = paramMap.size();
    }
    // 至少有一个参数时,循环拼接
    if (paramCount != 0) {
        // 先拼接"?"
        sb.append("?");
        // 遍历Key和value
        int pointer = 0;
        for (Map.Entry<String, String> entry : paramMap.entrySet()) {
            String key = entry.getKey();
            String value = (String) entry.getValue();
            //拼接数据
            sb.append(key).append("=").append(value);
            if (pointer != paramCount - 1) {
                sb.append("&");
                pointer++;
            }
        }
    }

    //3. 创建POST请求
    HttpPost httpPost = new HttpPost(url + sb.toString());
    httpPost.setConfig(requestConfig);

    //4. 声明响应模型
    CloseableHttpResponse response = null;

    //5. 发送请求
    try {
        //5-1. 由客户端执行(发送)POST请求
        response = httpClient.execute(httpPost);
        //5-2. 从响应模型中获取响应实体
        HttpEntity responseEntity = response.getEntity();
        //5-3. 将响应实体以UTF-8编码解析成JSON并返回
        return EntityUtils.toString(responseEntity, "utf-8");
    } catch (Exception e) {
        throw e;
    } finally {
        try {
            // 释放资源
            if (httpClient != null) {
                httpClient.close();
            }
            if (response != null) {
                response.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

2.5.有参POST请求:body参数

body参数一般指参数放在form-data中。

此时参数不再是拼接到url上了。当接口的形式参数是对象类型,发送请求时就需要将对象的json封装到form-data中。

注意:需要将请求头的Content-Type改成application/json;charset=utf8

/**
	 * 05. 参数在body的POST请求
	 *
	 * @param url
	 * @return
	 */
public static String postWithBody(String url, Object body) throws IOException {
    //1. 获得Http客户端
    CloseableHttpClient httpClient = HttpClientBuilder.create().build();

    //2. 处理请求参数
    StringEntity stringEntity = null;
    if (body != null) {
        //2-1. 将value值转换成JSON
        String jsonValue = JSON.toJSONString(body);
        //2-2. 以UTF-8编码将JSON值转换成stringEntity
        stringEntity = new StringEntity(jsonValue, "UTF-8");
    }

    //3. 创建POST请求
    HttpPost httpPost = new HttpPost(url);
    httpPost.setConfig(requestConfig);
    if (body != null) {
        //3-1. 将参数放入body中
        httpPost.setEntity(stringEntity);
        //3-2. 将请求头设置为json模式
        httpPost.setHeader("Content-Type", "application/json;charset=utf8");
    }


    //4. 声明响应模型
    CloseableHttpResponse response = null;

    //5. 发送请求
    try {
        //5-1. 由客户端执行(发送)Get请求
        response = httpClient.execute(httpPost);
        //5-2. 从响应模型中获取响应实体
        HttpEntity responseEntity = response.getEntity();
        //5-3. 将响应实体以UTF-8编码解析成JSON并返回
        return EntityUtils.toString(responseEntity, "utf-8");
    } catch (Exception e) {
        throw e;
    } finally {
        try {
            // 释放资源
            if (httpClient != null) {
                httpClient.close();
            }
            if (response != null) {
                response.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

2.6.有参POST请求:param参数 + body参数

本质上就是上述两种有参POST请求的加和。

将param参数拼接到url上,body参数放入form-data中并修改请求头即可。

/**
	 * 06. 参数同时在param和body中的POST请求
	 *
	 * @param url
	 * @param paramMap
	 * @param body
	 * @return
	 * @throws IOException
	 */
public static String postWithMix(String url, Map<String, String> paramMap, Object body) throws IOException {
    //1. 获取Http客户端
    CloseableHttpClient httpClient = HttpClientBuilder.create().build();

    //2. 处理param参数
    StringBuilder sb = new StringBuilder();
    int paramCount = 0;
    if(paramMap != null){
        paramCount = paramMap.size();
    }
    // 至少有一个参数时,循环拼接
    if (paramCount != 0) {
        // 先拼接"?"
        sb.append("?");
        // 遍历Key和value
        int pointer = 0;
        for (Map.Entry<String, String> entry : paramMap.entrySet()) {
            String key = entry.getKey();
            String value = (String) entry.getValue();
            //拼接数据
            sb.append(key).append("=").append(value);
            if (pointer != paramCount - 1) {
                sb.append("&");
                pointer++;
            }
        }
    }

    //3. 处理body参数
    StringEntity stringEntity = null;
    if (body != null) {
        //3-1. 将value值转换成JSON
        String jsonValue = JSON.toJSONString(body);
        //3-2. 以UTF-8编码将JSON值转换成stringEntity
        stringEntity = new StringEntity(jsonValue, "UTF-8");
    }

    //4. 创建POST请求
    //4-1. 加入param参数
    HttpPost httpPost = new HttpPost(url + sb.toString());
    httpPost.setConfig(requestConfig);
    if (body != null) {
        //4-2. 加入body参数
        httpPost.setEntity(stringEntity);
        //4-3. 将请求头设置为json模式
        httpPost.setHeader("Content-Type", "application/json;charset=utf8");
    }

    //5. 声明响应模型
    CloseableHttpResponse response = null;

    //6. 发送请求
    try {
        //6-1. 由客户端执行(发送)Get请求
        response = httpClient.execute(httpPost);
        //6-2. 从响应模型中获取响应实体
        HttpEntity responseEntity = response.getEntity();
        //6-3. 将响应实体以UTF-8编码解析成JSON并返回
        return EntityUtils.toString(responseEntity, "utf-8");
    } catch (Exception e) {
        throw e;
    } finally {
        try {
            // 释放资源
            if (httpClient != null) {
                httpClient.close();
            }
            if (response != null) {
                response.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

2.7.无参文件上传POST请求

文件上传则需要用到MultipartEntityBuilder这个类,在用MultipartFile构建完毕后,像body参数的POST请求一样将构建完毕的MultipartEntityBuilder赋给httpEntity,剩余操作完全一致。

注意:这里不用额外设置请求头

/**
	 * 07. 无参的文件上传POST请求
	 *
	 * @param fileMap
	 * @return
	 */
public static String postFile(String url, Map<String, MultipartFile> fileMap) throws IOException {
    //1. 获得Http客户端
    CloseableHttpClient httpClient = HttpClientBuilder.create().build();

    //2. 处理文件
    MultipartEntityBuilder builder = MultipartEntityBuilder.create();
    HttpEntity httpEntity = null;
    //2-1. 遍历map的key和value,获取所有文件
    if (fileMap != null) {
        for (Map.Entry<String, MultipartFile> entry : fileMap.entrySet()) {
            String key = entry.getKey();
            MultipartFile value = entry.getValue();
            //2-1. 文件加入到参数当中
            builder.addBinaryBody("file", value.getInputStream(), ContentType.APPLICATION_OCTET_STREAM, key);
            //2-2. 构建MultipartEntityBuilder,并赋值给HttpEntity
            httpEntity = builder.build();
        }
    }

    //3. 创建POST请求
    HttpPost httpPost = new HttpPost(url);
    httpPost.setConfig(requestConfig);
    if (fileMap != null) {
        httpPost.setEntity(httpEntity);
    }

    //4. 声明响应模型
    CloseableHttpResponse response = null;

    //5. 发送请求
    try {
        //5-1. 由客户端执行(发送)Get请求
        response = httpClient.execute(httpPost);
        //5-2. 从响应模型中获取响应实体
        HttpEntity responseEntity = response.getEntity();
        //5-3. 将响应实体以UTF-8编码解析成JSON并返回
        return EntityUtils.toString(responseEntity, "utf-8");
    } catch (Exception e) {
        throw e;
    } finally {
        try {
            // 释放资源
            if (httpClient != null) {
                httpClient.close();
            }
            if (response != null) {
                response.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

2.8.有参文件上传POST请求:param参数

其实就是param参数POST请求(2.4)与无参文件上传POST请求(2.7)的加和。

将param参数拼接到url上,文件则用MultipartFileBuilder构建并赋值给httpEntity。

/**
	 * 08. 参数在param的文件上传POST请求
	 *
	 * @param fileMap
	 * @return
	 */
public static String postFileWithParams(String url, Map<String, String> paramMap, Map<String, MultipartFile> fileMap) throws IOException {
    //1. 获得Http客户端
    CloseableHttpClient httpClient = HttpClientBuilder.create().build();

    //2. 处理param参数
    StringBuilder sb = new StringBuilder();
    int paramCount = 0;
    if(paramMap != null){
        paramCount = paramMap.size();
    }
    // 至少有一个参数时,循环拼接
    if (paramCount != 0) {
        // 先拼接"?"
        sb.append("?");
        // 遍历Key和value
        int pointer = 0;
        for (Map.Entry<String, String> entry : paramMap.entrySet()) {
            String key = entry.getKey();
            String value = (String) entry.getValue();
            //拼接数据
            sb.append(key).append("=").append(value);
            if (pointer != paramCount - 1) {
                sb.append("&");
                pointer++;
            }
        }
    }

    //3. 处理文件
    MultipartEntityBuilder builder = MultipartEntityBuilder.create();
    HttpEntity httpEntity = null;
    //3-1. 遍历map的key和value,获取所有文件
    if (fileMap != null) {
        for (Map.Entry<String, MultipartFile> entry : fileMap.entrySet()) {
            String key = entry.getKey();
            MultipartFile value = entry.getValue();
            //2-1. 文件加入到参数当中
            builder.addBinaryBody("file", value.getInputStream(), ContentType.APPLICATION_OCTET_STREAM, key);
            //2-2. 构建MultipartEntityBuilder,并赋值给HttpEntity
            httpEntity = builder.build();
        }
    }

    //4. 创建POST请求
    //4-1. 加入param参数
    HttpPost httpPost = new HttpPost(url + sb.toString());
    httpPost.setConfig(requestConfig);
    //4-2. 加入文件参数
    if (fileMap != null) {
        httpPost.setEntity(httpEntity);
    }

    //5. 声明响应模型
    CloseableHttpResponse response = null;

    //6. 发送请求
    try {
        //6-1. 由客户端执行(发送)Get请求
        response = httpClient.execute(httpPost);
        //6-2. 从响应模型中获取响应实体
        HttpEntity responseEntity = response.getEntity();
        //6-3. 将响应实体以UTF-8编码解析成JSON并返回
        return EntityUtils.toString(responseEntity, "utf-8");
    } catch (Exception e) {
        throw e;
    } finally {
        try {
            // 释放资源
            if (httpClient != null) {
                httpClient.close();
            }
            if (response != null) {
                response.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

3.代码整理:提出公共部分

分析上述代码,其实有很多代码都是在重复使用的。据此,可以将重复的部分提取出来,方便后期对代码的维护。

3.1.创建HttpGet

发送GET请求之前都需要创建HttpGet。将这部分代码提取出来,作为底层函数使用

/**
	 * 底层函数:创建httpGet
	 *
	 * @param url
	 * @param paramMap
	 * @return
	 */
public static HttpGet baseCreateHttpGet(String url, Map<String, String> paramMap) {
    //1. 设置param参数
    StringBuilder sb = new StringBuilder();
    int paramCount = 0;
    if (paramMap != null) {
        paramCount = paramMap.size();
    }
    // 至少有一个参数时,循环拼接
    if (paramCount != 0) {
        // 先拼接"?"
        sb.append("?");
        // 遍历Key和value
        int pointer = 0;
        for (Map.Entry<String, String> entry : paramMap.entrySet()) {
            String key = entry.getKey();
            String value = (String) entry.getValue();
            //拼接数据
            sb.append(key).append("=").append(value);
            if (pointer != paramCount - 1) {
                sb.append("&");
                pointer++;
            }
        }
    }
    //2. 创建GET请求
    HttpGet httpGet = new HttpGet(url + sb);
    httpGet.setConfig(requestConfig);
    return httpGet;
}

4.2.创建HttpPost

发送POST请求之前都需要创建HttpPost。将这部分代码提取出来,作为底层函数使用。

/**
	 * 底层函数:创建httpPost
	 *
	 * @param url
	 * @param paramMap
	 * @param body
	 * @return
	 */
private static HttpPost baseCreateHttpPost(String url, Map<String, String> paramMap, Object body) {
    //1. 处理param参数
    StringBuilder sb = new StringBuilder();
    int paramCount = 0;
    if (paramMap != null) {
        paramCount = paramMap.size();
    }
    // 至少有一个参数时,循环拼接
    if (paramCount != 0) {
        // 先拼接"?"
        sb.append("?");
        // 遍历Key和value
        int pointer = 0;
        for (Map.Entry<String, String> entry : paramMap.entrySet()) {
            String key = entry.getKey();
            String value = (String) entry.getValue();
            //拼接数据
            sb.append(key).append("=").append(value);
            if (pointer != paramCount - 1) {
                sb.append("&");
                pointer++;
            }
        }
    }

    //2. 处理body参数
    StringEntity stringEntity = null;
    if (body != null) {
        //3-1. 将value值转换成JSON
        String jsonValue = JSON.toJSONString(body);
        //3-2. 以UTF-8编码将JSON值转换成stringEntity
        stringEntity = new StringEntity(jsonValue, "UTF-8");
    }

    //3. 创建POST请求
    //3-1. 加入param参数
    HttpPost httpPost = new HttpPost(url + sb.toString());
    httpPost.setConfig(requestConfig);
    if (body != null) {
        //3-2. 加入body参数
        httpPost.setEntity(stringEntity);
        //3-3. 将请求头设置为json模式
        httpPost.setHeader("Content-Type", "application/json;charset=utf8");
    }
    return httpPost;
}

3.3.创建带文件的HttpPost

发送带文件的POST请求都需要将文件转换成StringEntity并赋值给httpEntity。据此将这部分代码单独提取出来作为底层函数调用。

/**
	 * 底层函数:创建携带文件的httpPost请求
	 *
	 * @param url
	 * @param paramMap
	 * @param fileMap
	 * @return
	 * @throws IOException
	 */
private static HttpPost baseCreateHttpPostWithFile(String url, Map<String, String> paramMap, Map<String, MultipartFile> fileMap) throws IOException {
    //1. 处理param参数
    StringBuilder sb = new StringBuilder();
    int paramCount = 0;
    if (paramMap != null) {
        paramCount = paramMap.size();
    }
    // 至少有一个参数时,循环拼接
    if (paramCount != 0) {
        // 先拼接"?"
        sb.append("?");
        // 遍历Key和value
        int pointer = 0;
        for (Map.Entry<String, String> entry : paramMap.entrySet()) {
            String key = entry.getKey();
            String value = (String) entry.getValue();
            //拼接数据
            sb.append(key).append("=").append(value);
            if (pointer != paramCount - 1) {
                sb.append("&");
                pointer++;
            }
        }
    }

    //2. 处理文件
    MultipartEntityBuilder builder = MultipartEntityBuilder.create();
    HttpEntity httpEntity = null;
    //2-1. 遍历map的key和value,获取所有文件
    if (fileMap != null) {
        for (Map.Entry<String, MultipartFile> entry : fileMap.entrySet()) {
            String key = entry.getKey();
            MultipartFile value = entry.getValue();
            //2-1. 文件加入到参数当中
            builder.addBinaryBody("file", value.getInputStream(), ContentType.APPLICATION_OCTET_STREAM, key);
            //2-2. 构建MultipartEntityBuilder,并赋值给HttpEntity
            httpEntity = builder.build();
        }
    }

    //3. 创建POST请求
    //3-1. 加入param参数
    HttpPost httpPost = new HttpPost(url + sb.toString());
    httpPost.setConfig(requestConfig);
    //3-2. 加入文件参数
    if (fileMap != null) {
        httpPost.setEntity(httpEntity);
    }
    return httpPost;
}

3.4.创建HttpClient并发送请求

上述不同方法中,实际上唯一的区别就在于它们的HttpGet或HttpPost有所不同。据此,将这部分代码提取出来,而HttpGet、HttpPost则提取出来作为方法的参数。

HttpGet和HttpPost继承了HttpRequestBase类,因此方法的形式参数类型确定为HttpRequestBase类。

/**
	 * 底层函数:发送请求
	 *
	 * @param httpRequestBase
	 * @return
	 * @throws IOException
	 */
private static String baseSendRequest(HttpRequestBase httpRequestBase) throws IOException {
    //1. 获得Http客户端
    CloseableHttpClient httpClient = HttpClientBuilder.create().build();

    //2. 声明响应模型
    CloseableHttpResponse response = null;

    //3. 发送请求
    try {
        //3-1. 由客户端执行(发送)请求
        response = httpClient.execute(httpRequestBase);
        //3-2. 从响应模型中获取响应实体
        HttpEntity responseEntity = response.getEntity();
        //3-3. 将响应实体以UTF-8编码解析成JSON并返回
        return EntityUtils.toString(responseEntity, "utf-8");
    } catch (Exception e) {
        throw e;
    } finally {
        try {
            // 释放资源
            if (httpClient != null) {
                httpClient.close();
            }
            if (response != null) {
                response.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

3.5.剩余代码

剩余代码就是根据不同的方法、参数,创建不同的请求,并创建httpClient、发送请求、获取响应。在公共部分都提取出来后,代码变得非常简洁。

/**
	 * 01. 无参GET请求
	 *
	 * @param url
	 * @return
	 */
public static String get(String url) throws IOException {
    //1. 创建httpGet
    HttpGet get = baseCreateHttpGet(url, null);
    //2. 发送请求,返回响应结果
    return baseSendRequest(get);
}

/**
	 * 02. 有参GET请求
	 *
	 * @param url
	 * @param paramMap
	 * @return
	 * @throws IOException
	 */
public static String getWithParams(String url, Map<String, String> paramMap) throws IOException {
    //1. 创建httpGet
    HttpGet get = baseCreateHttpGet(url, paramMap);
    //2. 发送请求,返回响应结果
    return baseSendRequest(get);
}

/**
	 * 03. 无参POST请求
	 *
	 * @param url
	 * @return
	 */
public static String post(String url) throws IOException {
    //1. 创建httpPost
    HttpPost post = baseCreateHttpPost(url, null, null);
    //2. 发送请求,返回响应结果
    return baseSendRequest(post);
}

/**
	 * 04. 参数在params的POST请求
	 *
	 * @param url
	 * @param paramMap
	 * @return
	 * @throws IOException
	 */
public static String postWithParams(String url, Map<String, String> paramMap) throws IOException {
    //1. 创建httpPost
    HttpPost post = baseCreateHttpPost(url, paramMap, null);
    //2. 发送请求,返回响应结果
    return baseSendRequest(post);
}

/**
	 * 05. 参数在body的POST请求
	 *
	 * @param url
	 * @return
	 */
public static String postWithBody(String url, Object body) throws IOException {
    //1. 创建httpPost
    HttpPost post = baseCreateHttpPost(url, null, body);
    //2. 发送请求,返回响应结果
    return baseSendRequest(post);
}

/**
	 * 06. 参数同时在param和body中的POST请求
	 *
	 * @param url
	 * @param paramMap
	 * @param body
	 * @return
	 * @throws IOException
	 */
public static String postWithMix(String url, Map<String, String> paramMap, Object body) throws IOException {
    //1. 创建httpPost
    HttpPost post = baseCreateHttpPost(url, paramMap, body);
    //2. 发送请求,返回响应结果
    return baseSendRequest(post);
}

/**
	 * 07. 无参的文件上传POST请求
	 *
	 * @param fileMap
	 * @return
	 */
public static String postFile(String url, Map<String, MultipartFile> fileMap) throws IOException {
    //1. 创建带文件的httpPost
    HttpPost post = baseCreateHttpPostWithFile(url, null, fileMap);
    //2. 发送请求,返回响应结果
    return baseSendRequest(post);
}

/**
	 * 08. 参数在param的文件上传POST请求
	 *
	 * @param fileMap
	 * @return
	 */
public static String postFileWithParams(String url, Map<String, String> paramMap, Map<String, MultipartFile> fileMap) throws IOException {
    //1. 创建带文件的httpPost
    HttpPost post = baseCreateHttpPostWithFile(url, paramMap, fileMap);
    //2. 发送请求,返回响应结果
    return baseSendRequest(post);
}

}

4.完整代码

4.1.整理前

package com.eshang.http.client.learning.util;

import com.alibaba.fastjson.JSON;
import org.apache.http.HttpEntity;
import org.apache.http.client.config.RequestConfig;
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.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.PostConstruct;
import java.io.IOException;
import java.util.Map;

/**
 * @author xyx-Eshang
 */
public class HttpClientUtil {

    private static RequestConfig requestConfig;

    @PostConstruct
    public void beforeInit() {
        // 配置信息
        HttpClientUtil.requestConfig = RequestConfig.custom()
            // 设置连接超时时间(单位毫秒)
            .setConnectTimeout(5000)
            // 设置请求超时时间(单位毫秒)
            .setConnectionRequestTimeout(5000)
            // socket读写超时时间(单位毫秒)
            .setSocketTimeout(5000)
            // 设置是否允许重定向(默认为true)
            .setRedirectsEnabled(true).build();
    }


    /**
	 * 01. 无参GET请求
	 *
	 * @param url
	 * @return
	 */
    public static String get(String url) throws IOException {
        //1. 获得Http客户端
        CloseableHttpClient httpClient = HttpClientBuilder.create().build();

        //2. 创建GET请求
        HttpGet httpGet = new HttpGet(url);
        httpGet.setConfig(requestConfig);

        //3. 声明响应模型
        CloseableHttpResponse response = null;

        //4. 发送请求
        try {
            //4-1. 由客户端执行(发送)Get请求
            response = httpClient.execute(httpGet);
            //4-2. 从响应模型中获取响应实体
            HttpEntity responseEntity = response.getEntity();
            //4-3. 将响应实体以UTF-8编码解析成JSON并返回
            return EntityUtils.toString(responseEntity, "utf-8");
        } catch (Exception e) {
            throw e;
        } finally {
            try {
                // 释放资源
                if (httpClient != null) {
                    httpClient.close();
                }
                if (response != null) {
                    response.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
	 * 02. 有参GET请求
	 *
	 * @param url
	 * @param paramMap
	 * @return
	 * @throws IOException
	 */
    public static String getWithParams(String url, Map<String, String> paramMap) throws IOException {
        //1. 获得Http客户端
        CloseableHttpClient httpClient = HttpClientBuilder.create().build();

        //2. 处理参数
        StringBuilder sb = new StringBuilder();
        int paramCount = paramMap.size();
        // 至少有一个参数时,循环拼接
        if (paramCount != 0) {
            // 先拼接"?"
            sb.append("?");
            // 遍历Key和value
            int pointer = 0;
            for (Map.Entry<String, String> entry : paramMap.entrySet()) {
                String key = entry.getKey();
                String value = (String) entry.getValue();
                //拼接数据
                sb.append(key).append("=").append(value);
                if (pointer != paramCount - 1) {
                    sb.append("&");
                    pointer++;
                }
            }
        }

        //3. 创建GET请求
        HttpGet httpGet = new HttpGet(url + sb.toString());
        httpGet.setConfig(requestConfig);

        //4. 声明响应模型
        CloseableHttpResponse response = null;

        //5. 发送请求
        try {
            //5-1. 由客户端执行(发送)Get请求
            response = httpClient.execute(httpGet);
            //5-2. 从响应模型中获取响应实体
            HttpEntity responseEntity = response.getEntity();
            //5-3. 将响应实体以UTF-8编码解析成JSON并返回
            return EntityUtils.toString(responseEntity, "utf-8");
        } catch (Exception e) {
            throw e;
        } finally {
            try {
                // 释放资源
                if (httpClient != null) {
                    httpClient.close();
                }
                if (response != null) {
                    response.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
	 * 03. 无参POST请求
	 *
	 * @param url
	 * @return
	 */
    public static String post(String url) throws IOException {
        //1. 获得Http客户端
        CloseableHttpClient httpClient = HttpClientBuilder.create().build();

        //2. 创建POST请求
        HttpPost httpPost = new HttpPost(url);
        httpPost.setConfig(requestConfig);

        //3. 声明响应模型
        CloseableHttpResponse response = null;

        //4. 发送请求
        try {
            //4-1. 由客户端执行(发送)Get请求
            response = httpClient.execute(httpPost);
            //4-2. 从响应模型中获取响应实体
            HttpEntity responseEntity = response.getEntity();
            //4-3. 将响应实体以UTF-8编码解析成JSON并返回
            return EntityUtils.toString(responseEntity, "utf-8");
        } catch (Exception e) {
            throw e;
        } finally {
            try {
                // 释放资源
                if (httpClient != null) {
                    httpClient.close();
                }
                if (response != null) {
                    response.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
	 * 04. 参数在params的POST请求
	 *
	 * @param url
	 * @param paramMap
	 * @return
	 * @throws IOException
	 */
    public static String postWithParams(String url, Map<String, String> paramMap) throws IOException {
        //1. 获得Http客户端
        CloseableHttpClient httpClient = HttpClientBuilder.create().build();

        //2. 处理参数
        StringBuilder sb = new StringBuilder();
        int paramCount = paramMap.size();
        // 至少有一个参数时,循环拼接
        if (paramCount != 0) {
            // 先拼接"?"
            sb.append("?");
            // 遍历Key和value
            int pointer = 0;
            for (Map.Entry<String, String> entry : paramMap.entrySet()) {
                String key = entry.getKey();
                String value = (String) entry.getValue();
                //拼接数据
                sb.append(key).append("=").append(value);
                if (pointer != paramCount - 1) {
                    sb.append("&");
                    pointer++;
                }
            }
        }

        //3. 创建POST请求
        HttpPost httpPost = new HttpPost(url + sb.toString());
        httpPost.setConfig(requestConfig);

        //4. 声明响应模型
        CloseableHttpResponse response = null;

        //5. 发送请求
        try {
            //5-1. 由客户端执行(发送)POST请求
            response = httpClient.execute(httpPost);
            //5-2. 从响应模型中获取响应实体
            HttpEntity responseEntity = response.getEntity();
            //5-3. 将响应实体以UTF-8编码解析成JSON并返回
            return EntityUtils.toString(responseEntity, "utf-8");
        } catch (Exception e) {
            throw e;
        } finally {
            try {
                // 释放资源
                if (httpClient != null) {
                    httpClient.close();
                }
                if (response != null) {
                    response.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
	 * 05. 参数在body的POST请求
	 *
	 * @param url
	 * @return
	 */
    public static String postWithBody(String url, Object body) throws IOException {
        //1. 获得Http客户端
        CloseableHttpClient httpClient = HttpClientBuilder.create().build();

        //2. 处理请求参数
        StringEntity stringEntity = null;
        String jsonValue;
        if (body != null) {
            //2-1. 将value值转换成JSON
            jsonValue = JSON.toJSONString(body);
            //2-2. 以UTF-8编码将JSON值转换成stringEntity
            stringEntity = new StringEntity(jsonValue, "UTF-8");
        }

        //3. 创建POST请求
        HttpPost httpPost = new HttpPost(url);
        httpPost.setConfig(requestConfig);
        if (body != null) {
            //3-1. 将参数放入body中
            httpPost.setEntity(stringEntity);
            //3-2. 将请求头设置为json模式
            httpPost.setHeader("Content-Type", "application/json;charset=utf8");
        }


        //4. 声明响应模型
        CloseableHttpResponse response = null;

        //5. 发送请求
        try {
            //5-1. 由客户端执行(发送)Get请求
            response = httpClient.execute(httpPost);
            //5-2. 从响应模型中获取响应实体
            HttpEntity responseEntity = response.getEntity();
            //5-3. 将响应实体以UTF-8编码解析成JSON并返回
            return EntityUtils.toString(responseEntity, "utf-8");
        } catch (Exception e) {
            throw e;
        } finally {
            try {
                // 释放资源
                if (httpClient != null) {
                    httpClient.close();
                }
                if (response != null) {
                    response.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
	 * 06. 参数同时在param和body中的POST请求
	 *
	 * @param url
	 * @param paramMap
	 * @param body
	 * @return
	 * @throws IOException
	 */
    public static String postWithMix(String url, Map<String, String> paramMap, Object body) throws IOException {
        //1. 获取Http客户端
        CloseableHttpClient httpClient = HttpClientBuilder.create().build();

        //2. 处理param参数
        StringBuilder sb = new StringBuilder();
        int paramCount = paramMap.size();
        // 至少有一个参数时,循环拼接
        if (paramCount != 0) {
            // 先拼接"?"
            sb.append("?");
            // 遍历Key和value
            int pointer = 0;
            for (Map.Entry<String, String> entry : paramMap.entrySet()) {
                String key = entry.getKey();
                String value = (String) entry.getValue();
                //拼接数据
                sb.append(key).append("=").append(value);
                if (pointer != paramCount - 1) {
                    sb.append("&");
                    pointer++;
                }
            }
        }

        //3. 处理body参数
        StringEntity stringEntity = null;
        String jsonValue = null;
        if (body != null) {
            //3-1. 将value值转换成JSON
            jsonValue = JSON.toJSONString(body);
            //3-2. 以UTF-8编码将JSON值转换成stringEntity
            stringEntity = new StringEntity(jsonValue, "UTF-8");
        }

        //4. 创建POST请求
        //4-1. 加入param参数
        HttpPost httpPost = new HttpPost(url + sb.toString());
        httpPost.setConfig(requestConfig);
        if (body != null) {
            //4-2. 加入body参数
            httpPost.setEntity(stringEntity);
            //4-3. 将请求头设置为json模式
            httpPost.setHeader("Content-Type", "application/json;charset=utf8");
        }

        //5. 声明响应模型
        CloseableHttpResponse response = null;

        //6. 发送请求
        try {
            //6-1. 由客户端执行(发送)Get请求
            response = httpClient.execute(httpPost);
            //6-2. 从响应模型中获取响应实体
            HttpEntity responseEntity = response.getEntity();
            //6-3. 将响应实体以UTF-8编码解析成JSON并返回
            return EntityUtils.toString(responseEntity, "utf-8");
        } catch (Exception e) {
            throw e;
        } finally {
            try {
                // 释放资源
                if (httpClient != null) {
                    httpClient.close();
                }
                if (response != null) {
                    response.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
	 * 07. 无参的文件上传POST请求
	 *
	 * @param fileMap
	 * @return
	 */
    public static String postFile(String url, Map<String, MultipartFile> fileMap) throws IOException {
        //1. 获得Http客户端
        CloseableHttpClient httpClient = HttpClientBuilder.create().build();

        //2. 处理文件
        MultipartEntityBuilder builder = MultipartEntityBuilder.create();
        HttpEntity httpEntity = null;
        //2-1. 遍历map的key和value,获取所有文件
        if (fileMap != null) {
            for (Map.Entry<String, MultipartFile> entry : fileMap.entrySet()) {
                String key = entry.getKey();
                MultipartFile value = entry.getValue();
                //2-1. 文件加入到参数当中
                builder.addBinaryBody("file", value.getInputStream(), ContentType.APPLICATION_OCTET_STREAM, key);
                //2-2. 构建MultipartEntityBuilder,并赋值给HttpEntity
                httpEntity = builder.build();
            }
        }

        //3. 创建POST请求
        HttpPost httpPost = new HttpPost(url);
        httpPost.setConfig(requestConfig);
        if (fileMap != null) {
            httpPost.setEntity(httpEntity);
        }

        //4. 声明响应模型
        CloseableHttpResponse response = null;

        //5. 发送请求
        try {
            //5-1. 由客户端执行(发送)Get请求
            response = httpClient.execute(httpPost);
            //5-2. 从响应模型中获取响应实体
            HttpEntity responseEntity = response.getEntity();
            //5-3. 将响应实体以UTF-8编码解析成JSON并返回
            return EntityUtils.toString(responseEntity, "utf-8");
        } catch (Exception e) {
            throw e;
        } finally {
            try {
                // 释放资源
                if (httpClient != null) {
                    httpClient.close();
                }
                if (response != null) {
                    response.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
	 * 08. 参数在param的文件上传POST请求
	 *
	 * @param fileMap
	 * @return
	 */
    public static String postFileWithParams(String url, Map<String, String> paramMap, Map<String, MultipartFile> fileMap) throws IOException {
        //1. 获得Http客户端
        CloseableHttpClient httpClient = HttpClientBuilder.create().build();

        //2. 处理param参数
        StringBuilder sb = new StringBuilder();
        int paramCount = paramMap.size();
        // 至少有一个参数时,循环拼接
        if (paramCount != 0) {
            // 先拼接"?"
            sb.append("?");
            // 遍历Key和value
            int pointer = 0;
            for (Map.Entry<String, String> entry : paramMap.entrySet()) {
                String key = entry.getKey();
                String value = (String) entry.getValue();
                //拼接数据
                sb.append(key).append("=").append(value);
                if (pointer != paramCount - 1) {
                    sb.append("&");
                    pointer++;
                }
            }
        }

        //3. 处理文件
        MultipartEntityBuilder builder = MultipartEntityBuilder.create();
        HttpEntity httpEntity = null;
        //3-1. 遍历map的key和value,获取所有文件
        if (fileMap != null) {
            for (Map.Entry<String, MultipartFile> entry : fileMap.entrySet()) {
                String key = entry.getKey();
                MultipartFile value = entry.getValue();
                //2-1. 文件加入到参数当中
                builder.addBinaryBody("file", value.getInputStream(), ContentType.APPLICATION_OCTET_STREAM, key);
                //2-2. 构建MultipartEntityBuilder,并赋值给HttpEntity
                httpEntity = builder.build();
            }
        }

        //4. 创建POST请求
        //4-1. 加入param参数
        HttpPost httpPost = new HttpPost(url + sb.toString());
        httpPost.setConfig(requestConfig);
        //4-2. 加入文件参数
        if (fileMap != null) {
            httpPost.setEntity(httpEntity);
        }

        //5. 声明响应模型
        CloseableHttpResponse response = null;

        //6. 发送请求
        try {
            //6-1. 由客户端执行(发送)Get请求
            response = httpClient.execute(httpPost);
            //6-2. 从响应模型中获取响应实体
            HttpEntity responseEntity = response.getEntity();
            //6-3. 将响应实体以UTF-8编码解析成JSON并返回
            return EntityUtils.toString(responseEntity, "utf-8");
        } catch (Exception e) {
            throw e;
        } finally {
            try {
                // 释放资源
                if (httpClient != null) {
                    httpClient.close();
                }
                if (response != null) {
                    response.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

4.2.整理后

package com.eshang.http.client.learning.util;

import com.alibaba.fastjson.JSON;
import org.apache.http.HttpEntity;
import org.apache.http.client.config.RequestConfig;
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.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.PostConstruct;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**
 * @author xyx-Eshang
 */
public class HttpClientUtil {

    private static RequestConfig requestConfig;

    @PostConstruct
    public void beforeInit() {
        // 配置信息
        HttpClientUtil.requestConfig = RequestConfig.custom()
            // 设置连接超时时间(单位毫秒)
            .setConnectTimeout(5000)
            // 设置请求超时时间(单位毫秒)
            .setConnectionRequestTimeout(5000)
            // socket读写超时时间(单位毫秒)
            .setSocketTimeout(5000)
            // 设置是否允许重定向(默认为true)
            .setRedirectsEnabled(true).build();
    }

    /**
	 * 底层函数:创建httpGet
	 *
	 * @param url
	 * @param paramMap
	 * @return
	 */
    public static HttpGet baseCreateHttpGet(String url, Map<String, String> paramMap) {
        //1. 设置param参数
        StringBuilder sb = new StringBuilder();
        int paramCount = 0;
        if (paramMap != null) {
            paramCount = paramMap.size();
        }
        // 至少有一个参数时,循环拼接
        if (paramCount != 0) {
            // 先拼接"?"
            sb.append("?");
            // 遍历Key和value
            int pointer = 0;
            for (Map.Entry<String, String> entry : paramMap.entrySet()) {
                String key = entry.getKey();
                String value = (String) entry.getValue();
                //拼接数据
                sb.append(key).append("=").append(value);
                if (pointer != paramCount - 1) {
                    sb.append("&");
                    pointer++;
                }
            }
        }
        //2. 创建GET请求
        HttpGet httpGet = new HttpGet(url + sb);
        httpGet.setConfig(requestConfig);
        return httpGet;
    }

    /**
	 * 底层函数:创建httpPost
	 *
	 * @param url
	 * @param paramMap
	 * @param body
	 * @return
	 */
    private static HttpPost baseCreateHttpPost(String url, Map<String, String> paramMap, Object body) {
        //1. 处理param参数
        StringBuilder sb = new StringBuilder();
        int paramCount = 0;
        if (paramMap != null) {
            paramCount = paramMap.size();
        }
        // 至少有一个参数时,循环拼接
        if (paramCount != 0) {
            // 先拼接"?"
            sb.append("?");
            // 遍历Key和value
            int pointer = 0;
            for (Map.Entry<String, String> entry : paramMap.entrySet()) {
                String key = entry.getKey();
                String value = (String) entry.getValue();
                //拼接数据
                sb.append(key).append("=").append(value);
                if (pointer != paramCount - 1) {
                    sb.append("&");
                    pointer++;
                }
            }
        }

        //2. 处理body参数
        StringEntity stringEntity = null;
        if (body != null) {
            //3-1. 将value值转换成JSON
            String jsonValue = JSON.toJSONString(body);
            //3-2. 以UTF-8编码将JSON值转换成stringEntity
            stringEntity = new StringEntity(jsonValue, "UTF-8");
        }

        //3. 创建POST请求
        //3-1. 加入param参数
        HttpPost httpPost = new HttpPost(url + sb.toString());
        httpPost.setConfig(requestConfig);
        if (body != null) {
            //3-2. 加入body参数
            httpPost.setEntity(stringEntity);
            //3-3. 将请求头设置为json模式
            httpPost.setHeader("Content-Type", "application/json;charset=utf8");
        }
        return httpPost;
    }

    /**
	 * 底层函数:创建携带文件的httpPost请求
	 *
	 * @param url
	 * @param paramMap
	 * @param fileMap
	 * @return
	 * @throws IOException
	 */
    private static HttpPost baseCreateHttpPostWithFile(String url, Map<String, String> paramMap, Map<String, MultipartFile> fileMap) throws IOException {
        //1. 处理param参数
        StringBuilder sb = new StringBuilder();
        int paramCount = 0;
        if (paramMap != null) {
            paramCount = paramMap.size();
        }
        // 至少有一个参数时,循环拼接
        if (paramCount != 0) {
            // 先拼接"?"
            sb.append("?");
            // 遍历Key和value
            int pointer = 0;
            for (Map.Entry<String, String> entry : paramMap.entrySet()) {
                String key = entry.getKey();
                String value = (String) entry.getValue();
                //拼接数据
                sb.append(key).append("=").append(value);
                if (pointer != paramCount - 1) {
                    sb.append("&");
                    pointer++;
                }
            }
        }

        //2. 处理文件
        MultipartEntityBuilder builder = MultipartEntityBuilder.create();
        HttpEntity httpEntity = null;
        //2-1. 遍历map的key和value,获取所有文件
        if (fileMap != null) {
            for (Map.Entry<String, MultipartFile> entry : fileMap.entrySet()) {
                String key = entry.getKey();
                MultipartFile value = entry.getValue();
                //2-1. 文件加入到参数当中
                builder.addBinaryBody("file", value.getInputStream(), ContentType.APPLICATION_OCTET_STREAM, key);
                //2-2. 构建MultipartEntityBuilder,并赋值给HttpEntity
                httpEntity = builder.build();
            }
        }

        //3. 创建POST请求
        //3-1. 加入param参数
        HttpPost httpPost = new HttpPost(url + sb.toString());
        httpPost.setConfig(requestConfig);
        //3-2. 加入文件参数
        if (fileMap != null) {
            httpPost.setEntity(httpEntity);
        }
        return httpPost;
    }

    /**
	 * 底层函数:发送请求
	 *
	 * @param httpRequestBase
	 * @return
	 * @throws IOException
	 */
    private static String baseSendRequest(HttpRequestBase httpRequestBase) throws IOException {
        //1. 获得Http客户端
        CloseableHttpClient httpClient = HttpClientBuilder.create().build();

        //2. 声明响应模型
        CloseableHttpResponse response = null;

        //3. 发送请求
        try {
            //3-1. 由客户端执行(发送)请求
            response = httpClient.execute(httpRequestBase);
            //3-2. 从响应模型中获取响应实体
            HttpEntity responseEntity = response.getEntity();
            //3-3. 将响应实体以UTF-8编码解析成JSON并返回
            return EntityUtils.toString(responseEntity, "utf-8");
        } catch (Exception e) {
            throw e;
        } finally {
            try {
                // 释放资源
                if (httpClient != null) {
                    httpClient.close();
                }
                if (response != null) {
                    response.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }


    /**
	 * 01. 无参GET请求
	 *
	 * @param url
	 * @return
	 */
    public static String get(String url) throws IOException {
        //1. 创建httpGet
        HttpGet get = baseCreateHttpGet(url, null);
        //2. 发送请求,返回响应结果
        return baseSendRequest(get);
    }

    /**
	 * 02. 有参GET请求
	 *
	 * @param url
	 * @param paramMap
	 * @return
	 * @throws IOException
	 */
    public static String getWithParams(String url, Map<String, String> paramMap) throws IOException {
        //1. 创建httpGet
        HttpGet get = baseCreateHttpGet(url, paramMap);
        //2. 发送请求,返回响应结果
        return baseSendRequest(get);
    }

    /**
	 * 03. 无参POST请求
	 *
	 * @param url
	 * @return
	 */
    public static String post(String url) throws IOException {
        //1. 创建httpPost
        HttpPost post = baseCreateHttpPost(url, null, null);
        //2. 发送请求,返回响应结果
        return baseSendRequest(post);
    }

    /**
	 * 04. 参数在params的POST请求
	 *
	 * @param url
	 * @param paramMap
	 * @return
	 * @throws IOException
	 */
    public static String postWithParams(String url, Map<String, String> paramMap) throws IOException {
        //1. 创建httpPost
        HttpPost post = baseCreateHttpPost(url, paramMap, null);
        //2. 发送请求,返回响应结果
        return baseSendRequest(post);
    }

    /**
	 * 05. 参数在body的POST请求
	 *
	 * @param url
	 * @return
	 */
    public static String postWithBody(String url, Object body) throws IOException {
        //1. 创建httpPost
        HttpPost post = baseCreateHttpPost(url, null, body);
        //2. 发送请求,返回响应结果
        return baseSendRequest(post);
    }

    /**
	 * 06. 参数同时在param和body中的POST请求
	 *
	 * @param url
	 * @param paramMap
	 * @param body
	 * @return
	 * @throws IOException
	 */
    public static String postWithMix(String url, Map<String, String> paramMap, Object body) throws IOException {
        //1. 创建httpPost
        HttpPost post = baseCreateHttpPost(url, paramMap, body);
        //2. 发送请求,返回响应结果
        return baseSendRequest(post);
    }

    /**
	 * 07. 无参的文件上传POST请求
	 *
	 * @param fileMap
	 * @return
	 */
    public static String postFile(String url, Map<String, MultipartFile> fileMap) throws IOException {
        //1. 创建带文件的httpPost
        HttpPost post = baseCreateHttpPostWithFile(url, null, fileMap);
        //2. 发送请求,返回响应结果
        return baseSendRequest(post);
    }

    /**
	 * 08. 参数在param的文件上传POST请求
	 *
	 * @param fileMap
	 * @return
	 */
    public static String postFileWithParams(String url, Map<String, String> paramMap, Map<String, MultipartFile> fileMap) throws IOException {
        //1. 创建带文件的httpPost
        HttpPost post = baseCreateHttpPostWithFile(url, paramMap, fileMap);
        //2. 发送请求,返回响应结果
        return baseSendRequest(post);
    }

}

5.进阶版

5.1.迭代一(2021.11.10)

  1. 新增带请求头的请求方法
  2. 所有方法返回类型都改为Map<String, Object>,包含响应头和请求信息。
  3. 响应头通过调用返回值的get(“header”)获取,类型为Map<String, Object>
  4. 响应体通过调用返回值的get(“body”)获取,类型为String(json)
package com.eshang.http.client.learning.util;

import com.alibaba.fastjson.JSON;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.client.config.RequestConfig;
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.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.PostConstruct;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**
 * @author xyx-Eshang
 */
public class HttpClientUtil {

    private static RequestConfig requestConfig;

    @PostConstruct
    public void beforeInit() {
        // 配置信息
        HttpClientUtil.requestConfig = RequestConfig.custom()
            // 设置连接超时时间(单位毫秒)
            .setConnectTimeout(5000)
            // 设置请求超时时间(单位毫秒)
            .setConnectionRequestTimeout(5000)
            // socket读写超时时间(单位毫秒)
            .setSocketTimeout(5000)
            // 设置是否允许重定向(默认为true)
            .setRedirectsEnabled(true).build();
    }

    /**
    * 底层函数:创建httpGet
    *
    * @param url
    * @param headerMap
    * @param paramMap
    * @return
    */
    public static HttpGet baseCreateHttpGet(Map<String, String> headerMap, String url, Map<String, String> paramMap) {
        //1. 设置param参数
        StringBuilder sb = new StringBuilder();
        int paramCount = 0;
        if (paramMap != null) {
            paramCount = paramMap.size();
        }
        // 至少有一个参数时,循环拼接
        if (paramCount != 0) {
            // 先拼接"?"
            sb.append("?");
            // 遍历Key和value
            int pointer = 0;
            for (Map.Entry<String, String> entry : paramMap.entrySet()) {
                String key = entry.getKey();
                String value = entry.getValue();
                //拼接数据
                sb.append(key).append("=").append(value);
                if (pointer != paramCount - 1) {
                    sb.append("&");
                    pointer++;
                }
            }
        }
        //2. 创建GET请求
        HttpGet httpGet = new HttpGet(url + sb);
        httpGet.setConfig(requestConfig);

        //3. 设置请求头
        if (headerMap != null && headerMap.size() != 0) {
            for (Map.Entry<String, String> entry : headerMap.entrySet()) {
                // 调用setHeader:无则添加,有则覆盖
                httpGet.setHeader(entry.getKey(), entry.getValue());
            }
        }
        return httpGet;
    }

    /**
    * 底层函数:创建httpPost
    *
    * @param url
    * @param headerMap
    * @param paramMap
    * @param body
    * @return
    */
    private static HttpPost baseCreateHttpPost(Map<String, String> headerMap, String url, Map<String, String> paramMap, Object body) {
        //1. 处理param参数
        StringBuilder sb = new StringBuilder();
        int paramCount = 0;
        if (paramMap != null) {
            paramCount = paramMap.size();
        }
        // 至少有一个参数时,循环拼接
        if (paramCount != 0) {
            // 先拼接"?"
            sb.append("?");
            // 遍历Key和value
            int pointer = 0;
            for (Map.Entry<String, String> entry : paramMap.entrySet()) {
                String key = entry.getKey();
                String value = entry.getValue();
                //拼接数据
                sb.append(key).append("=").append(value);
                if (pointer != paramCount - 1) {
                    sb.append("&");
                    pointer++;
                }
            }
        }

        //2. 处理body参数
        StringEntity stringEntity = null;
        if (body != null) {
            //3-1. 将value值转换成JSON
            String jsonValue = JSON.toJSONString(body);
            //3-2. 以UTF-8编码将JSON值转换成stringEntity
            stringEntity = new StringEntity(jsonValue, "UTF-8");
        }

        //3. 创建POST请求
        //3-1. 加入param参数
        HttpPost httpPost = new HttpPost(url + sb.toString());
        httpPost.setConfig(requestConfig);
        if (body != null) {
            //3-2. 加入body参数
            httpPost.setEntity(stringEntity);
            //3-3. 将请求头设置为json模式
            httpPost.setHeader("Content-Type", "application/json;charset=utf8");
        }

        //4. 设置请求头
        if (headerMap != null && headerMap.size() != 0) {
            for (Map.Entry<String, String> entry : headerMap.entrySet()) {
                // 调用setHeader:无则添加,有则覆盖
                httpPost.setHeader(entry.getKey(), entry.getValue());
            }
        }
        return httpPost;
    }

    /**
    * 底层函数:创建携带文件的httpPost请求
    *
    * @param url
    * @param headerMap
    * @param paramMap
    * @param fileMap
    * @return
    * @throws IOException
    */
    private static HttpPost baseCreateHttpPostWithFile(Map<String, String> headerMap, String url, Map<String, String> paramMap, Map<String, MultipartFile> fileMap) throws IOException {
        //1. 处理param参数
        StringBuilder sb = new StringBuilder();
        int paramCount = 0;
        if (paramMap != null) {
            paramCount = paramMap.size();
        }
        // 至少有一个参数时,循环拼接
        if (paramCount != 0) {
            // 先拼接"?"
            sb.append("?");
            // 遍历Key和value
            int pointer = 0;
            for (Map.Entry<String, String> entry : paramMap.entrySet()) {
                String key = entry.getKey();
                String value = entry.getValue();
                //拼接数据
                sb.append(key).append("=").append(value);
                if (pointer != paramCount - 1) {
                    sb.append("&");
                    pointer++;
                }
            }
        }

        //2. 处理文件
        MultipartEntityBuilder builder = MultipartEntityBuilder.create();
        HttpEntity httpEntity = null;
        //2-1. 遍历map的key和value,获取所有文件
        if (fileMap != null) {
            for (Map.Entry<String, MultipartFile> entry : fileMap.entrySet()) {
                String key = entry.getKey();
                MultipartFile value = entry.getValue();
                //2-1. 文件加入到参数当中
                builder.addBinaryBody("file", value.getInputStream(), ContentType.APPLICATION_OCTET_STREAM, key);
                //2-2. 构建MultipartEntityBuilder,并赋值给HttpEntity
                httpEntity = builder.build();
            }
        }

        //3. 创建POST请求
        //3-1. 加入param参数
        HttpPost httpPost = new HttpPost(url + sb.toString());
        httpPost.setConfig(requestConfig);
        //3-2. 加入文件参数
        if (fileMap != null) {
            httpPost.setEntity(httpEntity);
        }

        //4. 设置请求头
        if (headerMap != null && headerMap.size() != 0) {
            for (Map.Entry<String, String> entry : headerMap.entrySet()) {
                // 调用setHeader:无则添加,有则覆盖
                httpPost.setHeader(entry.getKey(), entry.getValue());
            }
        }
        return httpPost;
    }

    /**
    * 底层函数:发送请求
    *
    * @param httpRequestBase
    * @return
    * @throws IOException
    */
    private static Map<String, Object> baseSendRequest(HttpRequestBase httpRequestBase) throws IOException {
        //1. 获得Http客户端
        // 创建一个HttpClient
        CloseableHttpClient httpClient = HttpClientBuilder.create().build();
        //2. 声明响应模型
        CloseableHttpResponse response = null;
        //3. 发送请求
        try {
            //3-1. 由客户端执行(发送)请求
            response = httpClient.execute(httpRequestBase);
            //3-2. 从响应模型中获取响应实体
            HttpEntity responseEntity = response.getEntity();
            Map<String, Object> responseMap = new HashMap<>();
            //3-3. 获取响应头
            Header[] headerArray = response.getAllHeaders();
            Map<String, Object> headerMap = new HashMap<>();
            for (Header header : headerArray) {
                headerMap.put(header.getName(), header.getValue());
            }
            //3-4. 获取响应体,以UTF-8编码解析成JSON
            String body = EntityUtils.toString(responseEntity, "utf-8");
            //3-5. 封装,返回
            responseMap.put("headers", headerMap);
            responseMap.put("body", body);

            return responseMap;
        } catch (Exception e) {
            throw e;
        } finally {
            try {
                // 释放资源
                if (httpClient != null) {
                    httpClient.close();
                }
                if (response != null) {
                    response.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }


    /**
    * 01. 无参GET请求
    *
    * @param url
    * @return
    */
    public static Map<String, Object> get(String url) throws IOException {
        //1. 创建httpGet
        HttpGet get = baseCreateHttpGet(null, url, null);
        //2. 发送请求,返回响应结果
        return baseSendRequest(get);
    }

    /**
    * 02. 携带请求头的无参GET请求
    *
    * @param url
    * @param headerMap
    * @return
    * @throws IOException
    */
    public static Map<String, Object> get(Map<String, String> headerMap, String url) throws IOException {
        //1. 创建httpGet
        HttpGet get = baseCreateHttpGet(headerMap, url, null);
        //2. 发送请求,返回响应结果
        return baseSendRequest(get);
    }

    /**
    * 03. 有参GET请求
    *
    * @param url
    * @param paramMap
    * @return
    * @throws IOException
    */
    public static Map<String, Object> getWithParams(String url, Map<String, String> paramMap) throws IOException {
        //1. 创建httpGet
        HttpGet get = baseCreateHttpGet(null, url, paramMap);
        //2. 发送请求,返回响应结果
        return baseSendRequest(get);
    }

    /**
    * 04. 携带请求头的有参GET请求
    *
    * @param url
    * @param paramMap
    * @return
    * @throws IOException
    */
    public static Map<String, Object> getWithParams(Map<String, String> headerMap, String url, Map<String, String> paramMap) throws IOException {
        //1. 创建httpGet
        HttpGet get = baseCreateHttpGet(headerMap, url, paramMap);
        //2. 发送请求,返回响应结果
        return baseSendRequest(get);
    }

    /**
    * 05. 无参POST请求
    *
    * @param url
    * @return
    */
    public static Map<String, Object> post(String url) throws IOException {
        //1. 创建httpPost
        HttpPost post = baseCreateHttpPost(null, url, null, null);
        //2. 发送请求,返回响应结果
        return baseSendRequest(post);
    }


    /**
    * 06. 携带请求头的无参POST请求
    *
    * @param url
    * @return
    */
    public static Map<String, Object> post(Map<String, String> headerMap, String url) throws IOException {
        //1. 创建httpPost
        HttpPost post = baseCreateHttpPost(headerMap, url, null, null);
        //2. 发送请求,返回响应结果
        return baseSendRequest(post);
    }


    /**
    * 07. 参数在params的POST请求
    *
    * @param url
    * @param paramMap
    * @return
    * @throws IOException
    */
    public static Map<String, Object> postWithParams(String url, Map<String, String> paramMap) throws IOException {
        //1. 创建httpPost
        HttpPost post = baseCreateHttpPost(null, url, paramMap, null);
        //2. 发送请求,返回响应结果
        return baseSendRequest(post);
    }

    /**
    * 08. 携带请求头的参数在params的POST请求
    *
    * @param url
    * @param paramMap
    * @return
    * @throws IOException
    */
    public static Map<String, Object> postWithParams(Map<String, String> headerMap, String url, Map<String, String> paramMap) throws IOException {
        //1. 创建httpPost
        HttpPost post = baseCreateHttpPost(headerMap, url, paramMap, null);
        //2. 发送请求,返回响应结果
        return baseSendRequest(post);
    }


    /**
    * 09. 参数在body的POST请求
    *
    * @param url
    * @return
    */
    public static Map<String, Object> postWithBody(String url, Object body) throws IOException {
        //1. 创建httpPost
        HttpPost post = baseCreateHttpPost(null, url, null, body);
        //2. 发送请求,返回响应结果
        return baseSendRequest(post);
    }


    /**
    * 10. 携带请求头的参数在body的POST请求
    *
    * @param url
    * @return
    */
    public static Map<String, Object> postWithBody(Map<String, String> headerMap, String url, Object body) throws IOException {
        //1. 创建httpPost
        HttpPost post = baseCreateHttpPost(headerMap, url, null, body);
        //2. 发送请求,返回响应结果
        return baseSendRequest(post);
    }


    /**
    * 11. 参数同时在param和body中的POST请求
    *
    * @param url
    * @param paramMap
    * @param body
    * @return
    * @throws IOException
    */
    public static Map<String, Object> postWithMix(String url, Map<String, String> paramMap, Object body) throws IOException {
        //1. 创建httpPost
        HttpPost post = baseCreateHttpPost(null, url, paramMap, body);
        //2. 发送请求,返回响应结果
        return baseSendRequest(post);
    }

    /**
    * 12. 携带请求头的参数同时在param和body中的POST请求
    *
    * @param url
    * @param paramMap
    * @param body
    * @return
    * @throws IOException
    */
    public static Map<String, Object> postWithMix(Map<String, String> headerMap, String url, Map<String, String> paramMap, Object body) throws IOException {
        //1. 创建httpPost
        HttpPost post = baseCreateHttpPost(headerMap, url, paramMap, body);
        //2. 发送请求,返回响应结果
        return baseSendRequest(post);
    }

    /**
    * 13. 无参的文件上传POST请求
    *
    * @param fileMap
    * @return
    */
    public static Map<String, Object> postFile(String url, Map<String, MultipartFile> fileMap) throws IOException {
        //1. 创建带文件的httpPost
        HttpPost post = baseCreateHttpPostWithFile(null, url, null, fileMap);
        //2. 发送请求,返回响应结果
        return baseSendRequest(post);
    }

    /**
    * 14. 携带请求头的无参的文件上传POST请求
    *
    * @param fileMap
    * @return
    */
    public static Map<String, Object> postFile(Map<String, String> headerMap, String url, Map<String, MultipartFile> fileMap) throws IOException {
        //1. 创建带文件的httpPost
        HttpPost post = baseCreateHttpPostWithFile(headerMap, url, null, fileMap);
        //2. 发送请求,返回响应结果
        return baseSendRequest(post);
    }

    /**
    * 15. 参数在param的文件上传POST请求
    *
    * @param fileMap
    * @return
    */
    public static Map<String, Object> postFileWithParams(String url, Map<String, String> paramMap, Map<String, MultipartFile> fileMap) throws IOException {
        //1. 创建带文件的httpPost
        HttpPost post = baseCreateHttpPostWithFile(null, url, paramMap, fileMap);
        //2. 发送请求,返回响应结果
        return baseSendRequest(post);
    }


    /**
    * 16. 携带请求头的参数在param的文件上传POST请求
    *
    * @param fileMap
    * @return
    */
    public static Map<String, Object> postFileWithParams(Map<String, String> headerMap, String url, Map<String, String> paramMap, Map<String, MultipartFile> fileMap) throws IOException {
        //1. 创建带文件的httpPost
        HttpPost post = baseCreateHttpPostWithFile(headerMap, url, paramMap, fileMap);
        //2. 发送请求,返回响应结果
        return baseSendRequest(post);
    }

}

5.2.迭代二(2021.11.13)

输入的参数类型由Map<String, String>改为Map<String, Object>

package com.xyxeshang.es.music.backend.util;

import com.alibaba.fastjson.JSON;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.client.config.RequestConfig;
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.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.PostConstruct;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**
 * @author xyx-Eshang
 */
@SuppressWarnings("all")
public class HttpClientUtil {

    private static RequestConfig requestConfig;

    @PostConstruct
    public void beforeInit() {
        // 配置信息
        HttpClientUtil.requestConfig = RequestConfig.custom()
            // 设置连接超时时间(单位毫秒)
            .setConnectTimeout(5000)
            // 设置请求超时时间(单位毫秒)
            .setConnectionRequestTimeout(5000)
            // socket读写超时时间(单位毫秒)
            .setSocketTimeout(5000)
            // 设置是否允许重定向(默认为true)
            .setRedirectsEnabled(true).build();
    }

    /**
	 * 底层函数:创建httpGet
	 *
	 * @param url
	 * @param headerMap
	 * @param paramMap
	 * @return
	 */
    public static HttpGet baseCreateHttpGet(Map<String, String> headerMap, String url, Map<String, Object> paramMap) {
        //1. 设置param参数
        StringBuilder sb = new StringBuilder();
        int paramCount = 0;
        if (paramMap != null) {
            paramCount = paramMap.size();
        }
        // 至少有一个参数时,循环拼接
        if (paramCount != 0) {
            // 先拼接"?"
            sb.append("?");
            // 遍历Key和value
            int pointer = 0;
            for (Map.Entry<String, Object> entry : paramMap.entrySet()) {
                String key = entry.getKey();
                String value = "" + entry.getValue();
                //拼接数据
                sb.append(key).append("=").append(value);
                if (pointer != paramCount - 1) {
                    sb.append("&");
                    pointer++;
                }
            }
        }
        //2. 创建GET请求
        HttpGet httpGet = new HttpGet(url + sb);
        httpGet.setConfig(requestConfig);

        //3. 设置请求头
        if (headerMap != null && headerMap.size() != 0) {
            for (Map.Entry<String, String> entry : headerMap.entrySet()) {
                // 调用setHeader:无则添加,有则覆盖
                httpGet.setHeader(entry.getKey(), entry.getValue());
            }
        }
        return httpGet;
    }

    /**
	 * 底层函数:创建httpPost
	 *
	 * @param url
	 * @param headerMap
	 * @param paramMap
	 * @param body
	 * @return
	 */
    private static HttpPost baseCreateHttpPost(Map<String, String> headerMap, String url, Map<String, Object> paramMap, Object body) {
        //1. 处理param参数
        StringBuilder sb = new StringBuilder();
        int paramCount = 0;
        if (paramMap != null) {
            paramCount = paramMap.size();
        }
        // 至少有一个参数时,循环拼接
        if (paramCount != 0) {
            // 先拼接"?"
            sb.append("?");
            // 遍历Key和value
            int pointer = 0;
            for (Map.Entry<String, Object> entry : paramMap.entrySet()) {
                String key = entry.getKey();
                String value = "" + entry.getValue();
                //拼接数据
                sb.append(key).append("=").append(value);
                if (pointer != paramCount - 1) {
                    sb.append("&");
                    pointer++;
                }
            }
        }

        //2. 处理body参数
        StringEntity stringEntity = null;
        if (body != null) {
            //3-1. 将value值转换成JSON
            String jsonValue = JSON.toJSONString(body);
            //3-2. 以UTF-8编码将JSON值转换成stringEntity
            stringEntity = new StringEntity(jsonValue, "UTF-8");
        }

        //3. 创建POST请求
        //3-1. 加入param参数
        HttpPost httpPost = new HttpPost(url + sb.toString());
        httpPost.setConfig(requestConfig);
        if (body != null) {
            //3-2. 加入body参数
            httpPost.setEntity(stringEntity);
            //3-3. 将请求头设置为json模式
            httpPost.setHeader("Content-Type", "application/json;charset=utf8");
        }

        //4. 设置请求头
        if (headerMap != null && headerMap.size() != 0) {
            for (Map.Entry<String, String> entry : headerMap.entrySet()) {
                // 调用setHeader:无则添加,有则覆盖
                httpPost.setHeader(entry.getKey(), entry.getValue());
            }
        }
        return httpPost;
    }

    /**
	 * 底层函数:创建携带文件的httpPost请求
	 *
	 * @param url
	 * @param headerMap
	 * @param paramMap
	 * @param fileMap
	 * @return
	 * @throws IOException
	 */
    private static HttpPost baseCreateHttpPostWithFile(Map<String, String> headerMap, String url, Map<String, Object> paramMap, Map<String, MultipartFile> fileMap) throws IOException {
        //1. 处理param参数
        StringBuilder sb = new StringBuilder();
        int paramCount = 0;
        if (paramMap != null) {
            paramCount = paramMap.size();
        }
        // 至少有一个参数时,循环拼接
        if (paramCount != 0) {
            // 先拼接"?"
            sb.append("?");
            // 遍历Key和value
            int pointer = 0;
            for (Map.Entry<String, Object> entry : paramMap.entrySet()) {
                String key = entry.getKey();
                String value = "" + entry.getValue();
                //拼接数据
                sb.append(key).append("=").append(value);
                if (pointer != paramCount - 1) {
                    sb.append("&");
                    pointer++;
                }
            }
        }

        //2. 处理文件
        MultipartEntityBuilder builder = MultipartEntityBuilder.create();
        HttpEntity httpEntity = null;
        //2-1. 遍历map的key和value,获取所有文件
        if (fileMap != null) {
            for (Map.Entry<String, MultipartFile> entry : fileMap.entrySet()) {
                String key = entry.getKey();
                MultipartFile value = entry.getValue();
                //2-1. 文件加入到参数当中
                builder.addBinaryBody("file", value.getInputStream(), ContentType.APPLICATION_OCTET_STREAM, key);
                //2-2. 构建MultipartEntityBuilder,并赋值给HttpEntity
                httpEntity = builder.build();
            }
        }

        //3. 创建POST请求
        //3-1. 加入param参数
        HttpPost httpPost = new HttpPost(url + sb.toString());
        httpPost.setConfig(requestConfig);
        //3-2. 加入文件参数
        if (fileMap != null) {
            httpPost.setEntity(httpEntity);
        }

        //4. 设置请求头
        if (headerMap != null && headerMap.size() != 0) {
            for (Map.Entry<String, String> entry : headerMap.entrySet()) {
                // 调用setHeader:无则添加,有则覆盖
                httpPost.setHeader(entry.getKey(), entry.getValue());
            }
        }
        return httpPost;
    }

    /**
	 * 底层函数:发送请求
	 *
	 * @param httpRequestBase
	 * @return
	 * @throws IOException
	 */
    private static Map<String, Object> baseSendRequest(HttpRequestBase httpRequestBase) throws IOException {
        //1. 获得Http客户端
        // 创建一个HttpClient
        CloseableHttpClient httpClient = HttpClientBuilder.create().build();
        //2. 声明响应模型
        CloseableHttpResponse response = null;
        //3. 发送请求
        try {
            //3-1. 由客户端执行(发送)请求
            response = httpClient.execute(httpRequestBase);
            //3-2. 从响应模型中获取响应实体
            HttpEntity responseEntity = response.getEntity();
            Map<String, Object> responseMap = new HashMap<>();
            //3-3. 获取响应头
            Header[] headerArray = response.getAllHeaders();
            Map<String, Object> headerMap = new HashMap<>();
            for (Header header : headerArray) {
                headerMap.put(header.getName(), header.getValue());
            }
            //3-4. 获取响应体,以UTF-8编码解析成JSON
            String body = EntityUtils.toString(responseEntity, "utf-8");
            //3-5. 封装,返回
            responseMap.put("headers", headerMap);
            responseMap.put("body", body);

            return responseMap;
        } catch (Exception e) {
            throw e;
        } finally {
            try {
                // 释放资源
                if (httpClient != null) {
                    httpClient.close();
                }
                if (response != null) {
                    response.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }


    /**
	 * 01. 无参GET请求
	 *
	 * @param url
	 * @return
	 */
    public static Map<String, Object> get(String url) throws IOException {
        //1. 创建httpGet
        HttpGet get = baseCreateHttpGet(null, url, null);
        //2. 发送请求,返回响应结果
        return baseSendRequest(get);
    }

    /**
	 * 02. 携带请求头的无参GET请求
	 *
	 * @param url
	 * @param headerMap
	 * @return
	 * @throws IOException
	 */
    public static Map<String, Object> get(Map<String, String> headerMap, String url) throws IOException {
        //1. 创建httpGet
        HttpGet get = baseCreateHttpGet(headerMap, url, null);
        //2. 发送请求,返回响应结果
        return baseSendRequest(get);
    }

    /**
	 * 03. 有参GET请求
	 *
	 * @param url
	 * @param paramMap
	 * @return
	 * @throws IOException
	 */
    public static Map<String, Object> getWithParams(String url, Map<String, Object> paramMap) throws IOException {
        //1. 创建httpGet
        HttpGet get = baseCreateHttpGet(null, url, paramMap);
        //2. 发送请求,返回响应结果
        return baseSendRequest(get);
    }

    /**
	 * 04. 携带请求头的有参GET请求
	 *
	 * @param url
	 * @param paramMap
	 * @return
	 * @throws IOException
	 */
    public static Map<String, Object> getWithParams(Map<String, String> headerMap, String url, Map<String, Object> paramMap) throws IOException {
        //1. 创建httpGet
        HttpGet get = baseCreateHttpGet(headerMap, url, paramMap);
        //2. 发送请求,返回响应结果
        return baseSendRequest(get);
    }

    /**
	 * 05. 无参POST请求
	 *
	 * @param url
	 * @return
	 */
    public static Map<String, Object> post(String url) throws IOException {
        //1. 创建httpPost
        HttpPost post = baseCreateHttpPost(null, url, null, null);
        //2. 发送请求,返回响应结果
        return baseSendRequest(post);
    }


    /**
	 * 06. 携带请求头的无参POST请求
	 *
	 * @param url
	 * @return
	 */
    public static Map<String, Object> post(Map<String, String> headerMap, String url) throws IOException {
        //1. 创建httpPost
        HttpPost post = baseCreateHttpPost(headerMap, url, null, null);
        //2. 发送请求,返回响应结果
        return baseSendRequest(post);
    }


    /**
	 * 07. 参数在params的POST请求
	 *
	 * @param url
	 * @param paramMap
	 * @return
	 * @throws IOException
	 */
    public static Map<String, Object> postWithParams(String url, Map<String, Object> paramMap) throws IOException {
        //1. 创建httpPost
        HttpPost post = baseCreateHttpPost(null, url, paramMap, null);
        //2. 发送请求,返回响应结果
        return baseSendRequest(post);
    }

    /**
	 * 08. 携带请求头的参数在params的POST请求
	 *
	 * @param url
	 * @param paramMap
	 * @return
	 * @throws IOException
	 */
    public static Map<String, Object> postWithParams(Map<String, String> headerMap, String url, Map<String, Object> paramMap) throws IOException {
        //1. 创建httpPost
        HttpPost post = baseCreateHttpPost(headerMap, url, paramMap, null);
        //2. 发送请求,返回响应结果
        return baseSendRequest(post);
    }


    /**
	 * 09. 参数在body的POST请求
	 *
	 * @param url
	 * @return
	 */
    public static Map<String, Object> postWithBody(String url, Object body) throws IOException {
        //1. 创建httpPost
        HttpPost post = baseCreateHttpPost(null, url, null, body);
        //2. 发送请求,返回响应结果
        return baseSendRequest(post);
    }


    /**
	 * 10. 携带请求头的参数在body的POST请求
	 *
	 * @param url
	 * @return
	 */
    public static Map<String, Object> postWithBody(Map<String, String> headerMap, String url, Object body) throws IOException {
        //1. 创建httpPost
        HttpPost post = baseCreateHttpPost(headerMap, url, null, body);
        //2. 发送请求,返回响应结果
        return baseSendRequest(post);
    }


    /**
	 * 11. 参数同时在param和body中的POST请求
	 *
	 * @param url
	 * @param paramMap
	 * @param body
	 * @return
	 * @throws IOException
	 */
    public static Map<String, Object> postWithMix(String url, Map<String, Object> paramMap, Object body) throws IOException {
        //1. 创建httpPost
        HttpPost post = baseCreateHttpPost(null, url, paramMap, body);
        //2. 发送请求,返回响应结果
        return baseSendRequest(post);
    }

    /**
	 * 12. 携带请求头的参数同时在param和body中的POST请求
	 *
	 * @param url
	 * @param paramMap
	 * @param body
	 * @return
	 * @throws IOException
	 */
    public static Map<String, Object> postWithMix(Map<String, String> headerMap, String url, Map<String, Object> paramMap, Object body) throws IOException {
        //1. 创建httpPost
        HttpPost post = baseCreateHttpPost(headerMap, url, paramMap, body);
        //2. 发送请求,返回响应结果
        return baseSendRequest(post);
    }

    /**
	 * 13. 无参的文件上传POST请求
	 *
	 * @param fileMap
	 * @return
	 */
    public static Map<String, Object> postFile(String url, Map<String, MultipartFile> fileMap) throws IOException {
        //1. 创建带文件的httpPost
        HttpPost post = baseCreateHttpPostWithFile(null, url, null, fileMap);
        //2. 发送请求,返回响应结果
        return baseSendRequest(post);
    }

    /**
	 * 14. 携带请求头的无参的文件上传POST请求
	 *
	 * @param fileMap
	 * @return
	 */
    public static Map<String, Object> postFile(Map<String, String> headerMap, String url, Map<String, MultipartFile> fileMap) throws IOException {
        //1. 创建带文件的httpPost
        HttpPost post = baseCreateHttpPostWithFile(headerMap, url, null, fileMap);
        //2. 发送请求,返回响应结果
        return baseSendRequest(post);
    }

    /**
	 * 15. 参数在param的文件上传POST请求
	 *
	 * @param fileMap
	 * @return
	 */
    public static Map<String, Object> postFileWithParams(String url, Map<String, Object> paramMap, Map<String, MultipartFile> fileMap) throws IOException {
        //1. 创建带文件的httpPost
        HttpPost post = baseCreateHttpPostWithFile(null, url, paramMap, fileMap);
        //2. 发送请求,返回响应结果
        return baseSendRequest(post);
    }


    /**
	 * 16. 携带请求头的参数在param的文件上传POST请求
	 *
	 * @param fileMap
	 * @return
	 */
    public static Map<String, Object> postFileWithParams(Map<String, String> headerMap, String url, Map<String, Object> paramMap, Map<String, MultipartFile> fileMap) throws IOException {
        //1. 创建带文件的httpPost
        HttpPost post = baseCreateHttpPostWithFile(headerMap, url, paramMap, fileMap);
        //2. 发送请求,返回响应结果
        return baseSendRequest(post);
    }

}
  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值