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

文章目录

      • 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
            
            <dependency>
                <groupId>org.apache.httpcomponentsgroupId>
                <artifactId>httpclientartifactId>
                <version>${httpclient.version}version>
            dependency>
            <dependency>
                <groupId>org.apache.httpcomponentsgroupId>
                <artifactId>httpmimeartifactId>
                <version>${httpclient.version}version>
            dependency>

其中的版本为:

<httpclient.version>4.5.6httpclient.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":"[email protected]","userInsertTime":"2019-04-25 17:07:30","userUpdateTime":"2019-04-25 17:07:30","userStatus":1},{
     "id":4,"userName":"lily","userPasscode":"ed0de7252acf2980e677bacab01bde25","userEmail":"[email protected]","userInsertTime":"2019-04-25 17:07:30","userUpdateTime":"2019-04-25 17:07:30","userStatus":1},{
     "id":3,"userName":"jack","userPasscode":"ed0de7252acf2980e677bacab01bde25","userEmail":"[email protected]","userInsertTime":"2019-04-25 17:07:30","userUpdateTime":"2019-04-25 17:07:30","userStatus":1},{
     "id":2,"userName":"bob","userPasscode":"ed0de7252acf2980e677bacab01bde25","userEmail":"[email protected]","userInsertTime":"2019-04-25 17:07:30","userUpdateTime":"2019-04-25 17:07:30","userStatus":1},{
     "id":1,"userName":"tom","userPasscode":"ed0de7252acf2980e677bacab01bde25","userEmail":"[email protected]","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":"[email protected]","userInsertTime":"2019-04-25 17:07:30","userUpdateTime":"2019-04-25 17:07:30","userStatus":1},{
     "id":4,"userName":"lily","userPasscode":"ed0de7252acf2980e677bacab01bde25","userEmail":"[email protected]","userInsertTime":"2019-04-25 17:07:30","userUpdateTime":"2019-04-25 17:07:30","userStatus":1},{
     "id":3,"userName":"jack","userPasscode":"ed0de7252acf2980e677bacab01bde25","userEmail":"[email protected]","userInsertTime":"2019-04-25 17:07:30","userUpdateTime":"2019-04-25 17:07:30","userStatus":1},{
     "id":2,"userName":"bob","userPasscode":"ed0de7252acf2980e677bacab01bde25","userEmail":"[email protected]","userInsertTime":"2019-04-25 17:07:30","userUpdateTime":"2019-04-25 17:07:30","userStatus":1},{
     "id":1,"userName":"tom","userPasscode":"ed0de7252acf2980e677bacab01bde25","userEmail":"[email protected]","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":"[email protected]","userInsertTime":"2019-04-25 17:07:30","userUpdateTime":"2019-04-25 17:07:30","userStatus":1},{
     "id":4,"userName":"lily","userPasscode":"ed0de7252acf2980e677bacab01bde25","userEmail":"[email protected]","userInsertTime":"2019-04-25 17:07:30","userUpdateTime":"2019-04-25 17:07:30","userStatus":1},{
     "id":3,"userName":"jack","userPasscode":"ed0de7252acf2980e677bacab01bde25","userEmail":"[email protected]","userInsertTime":"2019-04-25 17:07:30","userUpdateTime":"2019-04-25 17:07:30","userStatus":1},{
     "id":2,"userName":"bob","userPasscode":"ed0de7252acf2980e677bacab01bde25","userEmail":"[email protected]","userInsertTime":"2019-04-25 17:07:30","userUpdateTime":"2019-04-25 17:07:30","userStatus":1},{
     "id":1,"userName":"tom","userPasscode":"ed0de7252acf2980e677bacab01bde25","userEmail":"[email protected]","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

个人公众号:404Code,分享半个互联网人的技术与思考,感兴趣的可以关注.
404Code

你可能感兴趣的:(Java,java,HttpClient,POST,upload,文件上传)