Spring Boot 2.X 项目使用 Apache HttpClient 发送请求与上传文件(简易使用)

发布时间 2023-03-22 21:16:36作者: kelelipeng

文件来源:

https://blog.csdn.net/Mrqiang9001/article/details/90271675

 

文章目录
1 摘要
2 Maven 依赖
3 HttpClient 网络请求工具类
4 应用与测试
4.1 测试类
4.2 GET 请求测试
4.3 POST 请求-URL拼接参数
4.4 POST请求-JSON参数
4.5 POST请求-文件上传
5 参考资料推荐
6 Github 源码
1 摘要
java 项目中网络请求是一个常用的功能。jdk 自带的网络工具类(java.net)效率低下,因此推荐使用第三方的网络库。Apache HttpClient 库深受广大开发者的欢迎。本文将介绍在 Spring Boot 2.X 项目中简单使用基于 Apache Httpclient 4.5.X 发送请求与上传文件。

Apache HttpClient 官方文档: https://hc.apache.org/httpcomponents-client-ga/quickstart.html

2 Maven 依赖 

../pom.xml
../demo-common/pom.xml
            <!-- Apache httpClient -->
            <dependency>
                <groupId>org.apache.httpcomponents</groupId>
                <artifactId>httpclient</artifactId>
                <version>${httpclient.version}</version>
            </dependency>
            <dependency>
                <groupId>org.apache.httpcomponents</groupId>
                <artifactId>httpmime</artifactId>
                <version>${httpclient.version}</version>
            </dependency>

 其中的版本为:

<httpclient.version>4.5.6</httpclient.version>

 

 

3 HttpClient 网络请求工具类

../demo-common/src/main/java/com/ljq/demo/springboot/common/util/SimpleHttpClientUtil.java

 

package com.ljq.demo.springboot.common.util;

import org.apache.http.Consts;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
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.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.protocol.HTTP;

import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;
import java.util.Map;

/**
 * @Description: 网络请求工具类--Powered by Apache HttpClient
 * @Author: junqiang.lu
 * @Date: 2019/5/16
 */
public class SimpleHttpClientUtil implements Serializable {

    private static final long serialVersionUID = 4634161754990919271L;

    private static volatile HttpClient httpClient;

    private SimpleHttpClientUtil(){}


    /**
     * GET 方式请求
     * 参数通过 url 拼接
     *
     * @param host 请求地址
     * @param path 接口路径
     * @param paramsMap 请求参数
     * @return
     * @throws IOException
     */
    public static HttpResponse doGet(String host, String path, Map<String, String> paramsMap) throws IOException {
        initHttpClient();
        RequestConfig requestConfig = RequestConfig.custom()
                .setConnectionRequestTimeout(10000)
                .setConnectTimeout(5000)
                .build();
        HttpGet httpGet = new HttpGet(getRequestUrl(host, path, paramsMap));
        httpGet.setConfig(requestConfig);
        httpGet.setHeader(HTTP.CONTENT_TYPE,ContentType.create(ContentType.APPLICATION_FORM_URLENCODED
                .getMimeType(),Consts.UTF_8).toString());

        return httpClient.execute(httpGet);
    }

    /**
     * POST 方式请求
     * 参数通过 url 拼接
     *
     * @param host 请求地址
     * @param path 接口路径
     * @param paramsMap 请求参数
     * @return
     * @throws IOException
     */
    public static HttpResponse doPost(String host, String path, Map<String, String> paramsMap) throws IOException {
        initHttpClient();
        RequestConfig requestConfig = RequestConfig.custom()
                .setConnectionRequestTimeout(10000)
                .setConnectTimeout(5000)
                .build();
        HttpPost httpPost = new HttpPost(getRequestUrl(host, path, paramsMap));
        httpPost.setConfig(requestConfig);
        httpPost.setHeader(HTTP.CONTENT_TYPE,ContentType.create(ContentType.APPLICATION_FORM_URLENCODED
                .getMimeType(),Consts.UTF_8).toString());

        return httpClient.execute(httpPost);
    }

    /**
     * POST 方式请求
     * 参数通过 Body 传送,JSON 格式
     *
     * @param host 请求地址
     * @param path 接口路径
     * @param jsonParams 请求参数(json 字符串)
     * @return
     */
    public static HttpResponse doPost(String host, String path, String jsonParams) throws IOException {
        initHttpClient();
        RequestConfig requestConfig = RequestConfig.custom()
                .setConnectionRequestTimeout(10000)
                .setConnectTimeout(5000)
                .build();
        HttpPost httpPost = new HttpPost(host + path);
        StringEntity stringentity = new StringEntity(jsonParams, ContentType.APPLICATION_JSON);
        httpPost.setEntity(stringentity);
        httpPost.setConfig(requestConfig);
        httpPost.addHeader(HTTP.CONTENT_TYPE, ContentType.APPLICATION_JSON.toString());

        return httpClient.execute(httpPost);
    }

    /**
     * POST 方式请求
     * 文件上传
     *
     * @param host 请求地址
     * @param path 接口路径
     * @param paramsMap 请求参数
     * @param fileInputStream 待上传文件流
     * @param name 文件对应字段名
     * @param fileOriginalName 原始文件名
     * @return
     */
    public static HttpResponse doPost(String host, String path, Map<String, String> paramsMap,
                                      InputStream fileInputStream, String name, String fileOriginalName) throws IOException {
        initHttpClient();
        RequestConfig requestConfig = RequestConfig.custom()
                .setConnectionRequestTimeout(10000)
                .setConnectTimeout(5000)
                .build();
        HttpPost httpPost = new HttpPost(host + path);
        MultipartEntityBuilder entityBuilder = MultipartEntityBuilder.create();
        // 解决中文文件名乱码问题
        entityBuilder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
        entityBuilder.setCharset(Consts.UTF_8);
        ContentType contentType = ContentType.create(ContentType.TEXT_PLAIN.getMimeType(), Consts.UTF_8);
        for (Map.Entry<String, String> entry : paramsMap.entrySet()) {
            entityBuilder.addTextBody(entry.getKey(), entry.getValue(), contentType);
        }
        if (fileInputStream != null && name != null && fileOriginalName != null) {
            entityBuilder.addBinaryBody(name, fileInputStream, ContentType.DEFAULT_BINARY, fileOriginalName);
        }
        httpPost.setEntity(entityBuilder.build());
        httpPost.setConfig(requestConfig);

        return httpClient.execute(httpPost);
    }



    /**
     * 初始化 httpClient
     * @return
     */
    private static HttpClient initHttpClient() {
        if  (httpClient == null) {
            synchronized (SimpleHttpClientUtil.class) {
                if (httpClient == null) {
                    httpClient = HttpClients.createDefault();
                }
            }
        }
        return httpClient;
    }

    /**
     * 获取完整请求地址(包含参数)
     * 参数拼接在 url 中
     *
     * @param host 请求地址
     * @param path 接口路径
     * @param paramsMap 请求参数
     * @return
     */
    private static String getRequestUrl(String host, String path, Map<String, String> paramsMap) {
        StringBuilder reqUrl = new StringBuilder(host).append(path);
        if (paramsMap != null && !paramsMap.isEmpty()) {
            StringBuilder params = new StringBuilder();
            for (Map.Entry<String, String> entry : paramsMap.entrySet()) {
                params.append("&" + entry.getKey() + "=" + entry.getValue());
            }
            String paramConnector = "?";
            if (!host.contains(paramConnector) && !path.contains(paramConnector)) {
                reqUrl.append(paramConnector);
                reqUrl.append(params.toString().substring(1));
            } else {
                reqUrl.append(params.toString());
            }
        }

        return reqUrl.toString();
    }


}

4 应用与测试
4.1 测试类

../demo-web/src/test/java/com/ljq/demo/springboot/common/util/SimpleHttpClientUtilTest.java

 

package com.ljq.demo.springboot.common.util;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.http.HttpResponse;
import org.apache.http.util.EntityUtils;
import org.junit.Test;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;

public class SimpleHttpClientUtilTest {

    private static String API_HOST = "http://192.168.100.100:8848";
    private static String API_PATH_USER_LIST = "/api/user/list";
    private static String API_PATH_USER_LISTS = "/api/user/lists";
    private static String API_PATH_COMMON_UPLOAD = "/api/demo/common/upload";


    @Test
    public void doGet() throws IOException {
        String paramsStr = "?demoKey=demoValue";
        Map<String, String> paramsMap = new HashMap<>(16);
        paramsMap.put("demoMapKey", "demoMapValue");
        paramsMap.put("zhTest", "德玛西亚");

        HttpResponse httpResponse = SimpleHttpClientUtil.doGet(API_HOST, API_PATH_USER_LIST + paramsStr, paramsMap);

        printHttpResponse(httpResponse);
    }

    @Test
    public void doPostJson() throws IOException {
        Map<String, String> paramsMap = new HashMap<>(16);
        paramsMap.put("demoMapKey", "demoMapValue");
        paramsMap.put("zhTest", "德玛西亚");

        HttpResponse httpResponse = SimpleHttpClientUtil.doPost(API_HOST, API_PATH_USER_LIST, new ObjectMapper().writeValueAsString(paramsMap));

        printHttpResponse(httpResponse);

    }

    @Test
    public void doPostUrl() throws IOException {
        Map<String, String> paramsMap = new HashMap<>(16);
        paramsMap.put("demoMapKey", "demoMapValue");
        paramsMap.put("zhTest", "德玛西亚");

        HttpResponse httpResponse = SimpleHttpClientUtil.doPost(API_HOST, API_PATH_USER_LISTS, paramsMap);

        printHttpResponse(httpResponse);

    }

    @Test
    public void doPostMultipart() throws IOException {
        Map<String, String> paramsMap = new HashMap<>(16);
        paramsMap.put("demoMapKey", "demoMapValue");
        paramsMap.put("zhTest", "德玛西亚");
        Path path = Paths.get("F:\\download\\阿里巴巴Java开发手册(详尽版).pdf");
        String name = "file";
        String fileOriginalName = "阿里巴巴Java开发手册(详尽版).pdf";

        HttpResponse httpResponse = SimpleHttpClientUtil.doPost(API_HOST, API_PATH_COMMON_UPLOAD, paramsMap,
                Files.newInputStream(path),name, fileOriginalName);

        printHttpResponse(httpResponse);

    }


    /**
     * 打印 http 请求结果
     *
     * @param httpResponse
     * @throws IOException
     */
    public static void printHttpResponse(HttpResponse httpResponse) throws IOException {
        System.out.println("response Code: " + httpResponse.getStatusLine().getStatusCode());

        System.out.println(EntityUtils.toString(httpResponse.getEntity()));
    }


}

 

4.2 GET 请求测试
请求日志: 

2019-05-16 19:49:02:919 [http-nio-8848-exec-2] INFO  com.ljq.demo.springboot.web.acpect.LogAspect(LogAspect.java 67) -[AOP-LOG-START]
        requestMark: ee0a1d50-d943-42aa-ab63-5505f04de027
        requestIP: 192.168.100.1
        contentType:application/x-www-form-urlencoded; charset=UTF-8
        requestUrl: http://192.168.100.100:8848/api/user/list
        requestMethod: GET
        requestParams: demoKey = demoValue;zhTest = 德玛西亚;demoMapKey = demoMapValue;
        targetClassAndMethod: com.ljq.demo.springboot.web.controller.UserController#queryList

 

返回结果: 

response Code: 200
{"code":1000,"msg":"成功","data":[{"id":5,"userName":"liming","userPasscode":"ed0de7252acf2980e677bacab01bde25","userEmail":"liming@example.com","userInsertTime":"2019-04-25 17:07:30","userUpdateTime":"2019-04-25 17:07:30","userStatus":1},{"id":4,"userName":"lily","userPasscode":"ed0de7252acf2980e677bacab01bde25","userEmail":"lily@example.com","userInsertTime":"2019-04-25 17:07:30","userUpdateTime":"2019-04-25 17:07:30","userStatus":1},{"id":3,"userName":"jack","userPasscode":"ed0de7252acf2980e677bacab01bde25","userEmail":"jack@example.com","userInsertTime":"2019-04-25 17:07:30","userUpdateTime":"2019-04-25 17:07:30","userStatus":1},{"id":2,"userName":"bob","userPasscode":"ed0de7252acf2980e677bacab01bde25","userEmail":"bob@example.com","userInsertTime":"2019-04-25 17:07:30","userUpdateTime":"2019-04-25 17:07:30","userStatus":1},{"id":1,"userName":"tom","userPasscode":"ed0de7252acf2980e677bacab01bde25","userEmail":"tom@example.com","userInsertTime":"2019-04-25 17:07:30","userUpdateTime":"2019-04-25 17:07:30","userStatus":1}]}

 

4.3 POST 请求-URL拼接参数
请求日志:

2019-05-16 20:13:28:509 [http-nio-8848-exec-4] INFO  com.ljq.demo.springboot.web.acpect.LogAspect(LogAspect.java 67) -[AOP-LOG-START]
        requestMark: c7e7d6d0-873b-440e-bb24-270abde33e7f
        requestIP: 192.168.100.1
        contentType:application/x-www-form-urlencoded; charset=UTF-8
        requestUrl: http://192.168.100.100:8848/api/user/lists
        requestMethod: POST
        requestParams: zhTest = 德玛西亚;demoMapKey = demoMapValue;
        targetClassAndMethod: com.ljq.demo.springboot.web.controller.UserController#queryLists

 

返回结果: 

response Code: 200
{"code":1000,"msg":"成功","data":[{"id":5,"userName":"liming","userPasscode":"ed0de7252acf2980e677bacab01bde25","userEmail":"liming@example.com","userInsertTime":"2019-04-25 17:07:30","userUpdateTime":"2019-04-25 17:07:30","userStatus":1},{"id":4,"userName":"lily","userPasscode":"ed0de7252acf2980e677bacab01bde25","userEmail":"lily@example.com","userInsertTime":"2019-04-25 17:07:30","userUpdateTime":"2019-04-25 17:07:30","userStatus":1},{"id":3,"userName":"jack","userPasscode":"ed0de7252acf2980e677bacab01bde25","userEmail":"jack@example.com","userInsertTime":"2019-04-25 17:07:30","userUpdateTime":"2019-04-25 17:07:30","userStatus":1},{"id":2,"userName":"bob","userPasscode":"ed0de7252acf2980e677bacab01bde25","userEmail":"bob@example.com","userInsertTime":"2019-04-25 17:07:30","userUpdateTime":"2019-04-25 17:07:30","userStatus":1},{"id":1,"userName":"tom","userPasscode":"ed0de7252acf2980e677bacab01bde25","userEmail":"tom@example.com","userInsertTime":"2019-04-25 17:07:30","userUpdateTime":"2019-04-25 17:07:30","userStatus":1}]}

 

4.4 POST请求-JSON参数
请求日志:

2019-05-16 20:15:26:249 [http-nio-8848-exec-5] INFO  com.ljq.demo.springboot.web.acpect.LogAspect(LogAspect.java 67) -[AOP-LOG-START]
        requestMark: f94612bd-dcc9-4b7b-9c77-2b296cd00948
        requestIP: 192.168.100.1
        contentType:application/json; charset=UTF-8
        requestUrl: http://192.168.100.100:8848/api/user/list
        requestMethod: POST
        requestParams: {"zhTest":"德玛西亚","demoMapKey":"demoMapValue"}
        targetClassAndMethod: com.ljq.demo.springboot.web.controller.UserController#queryList

返回结果:

response Code: 200
{"code":1000,"msg":"成功","data":[{"id":5,"userName":"liming","userPasscode":"ed0de7252acf2980e677bacab01bde25","userEmail":"liming@example.com","userInsertTime":"2019-04-25 17:07:30","userUpdateTime":"2019-04-25 17:07:30","userStatus":1},{"id":4,"userName":"lily","userPasscode":"ed0de7252acf2980e677bacab01bde25","userEmail":"lily@example.com","userInsertTime":"2019-04-25 17:07:30","userUpdateTime":"2019-04-25 17:07:30","userStatus":1},{"id":3,"userName":"jack","userPasscode":"ed0de7252acf2980e677bacab01bde25","userEmail":"jack@example.com","userInsertTime":"2019-04-25 17:07:30","userUpdateTime":"2019-04-25 17:07:30","userStatus":1},{"id":2,"userName":"bob","userPasscode":"ed0de7252acf2980e677bacab01bde25","userEmail":"bob@example.com","userInsertTime":"2019-04-25 17:07:30","userUpdateTime":"2019-04-25 17:07:30","userStatus":1},{"id":1,"userName":"tom","userPasscode":"ed0de7252acf2980e677bacab01bde25","userEmail":"tom@example.com","userInsertTime":"2019-04-25 17:07:30","userUpdateTime":"2019-04-25 17:07:30","userStatus":1}]}

 

4.5 POST请求-文件上传
请求日志:

2019-05-16 20:16:56:569 [http-nio-8848-exec-7] INFO  com.ljq.demo.springboot.web.acpect.LogAspect(LogAspect.java 67) -[AOP-LOG-START]
        requestMark: 3a4eb27e-c35b-4804-bda1-100c0a1b89d9
        requestIP: 192.168.100.1
        contentType:multipart/form-data; boundary=-e08loTIIPoPhChkhGqIWqy4J9HX7REn; charset=UTF-8
        requestUrl: http://192.168.100.100:8848/api/demo/common/upload
        requestMethod: POST
        requestParams: zhTest = 德玛西亚;demoMapKey = demoMapValue;fileSize = 1163395;fileContentType = application/octet-stream;fieldName = file;fileOriginalName = 阿里巴巴Java开发手册(详尽版).pdf;
        targetClassAndMethod: com.ljq.demo.springboot.web.controller.CommonController#upload

返回参数: 

response Code: 200
{"code":1000,"msg":"成功","data":null}

 

5 参考资料推荐

官方文档 HttpClient Quick Start

官方文档 HttpClient Examples

解决httpclient上传文件的时候中文文件名乱码的问题

6 Github 源码
Gtihub 源码地址 : https://github.com/Flying9001/springBootDemo