HttpClient4.5.6的Fluent工具集

本文参考自 整理HttpClient4.5的Fluent API的用法 ,如有侵权,请作者联系删除。

MAVEN依赖

<!-- java端模拟浏览器发送请求 -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
    <artifactId>fluent-hc</artifactId>
    <version>4.5.6</version>
</dependency>
<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
    <version>4.5.6</version>
</dependency>
<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpmime</artifactId>
    <version>4.5.6</version>
</dependency>
<!-- 工具集 -->
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-lang3</artifactId>
    <version>3.8.1</version>
</dependency>
<dependency>
    <groupId>org.apache.velocity</groupId>
    <artifactId>velocity</artifactId>
    <version>1.7</version>
</dependency>
<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>27.0-jre</version>
</dependency>
<dependency>
    <groupId>commons-beanutils</groupId>
    <artifactId>commons-beanutils</artifactId>
    <version>1.9.3</version>
</dependency>

fluent静态工具类

package vip.coinbag.managemoneymatters.common.http;

import org.apache.commons.beanutils.BeanMap;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.Consts;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.NameValuePair;
import org.apache.http.client.fluent.Request;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.util.Args;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.Map;

/**
 * <p>类描述:Apache HttpClient Fluent快速发送GET/POST访问,目前不支持需要登录的操作,待后续完善。</p>
 * @author wzx
 * @time 2018/11/1
 */
public class HttpFluent {

    private static final Logger LOGGER = LoggerFactory.getLogger(HttpFluent.class);
    private static final Integer CONNECT_TIMEOUT = 5000;   // 连接超时5s
    private static final Integer SOCKET_TIMEOUT = 30000;   // 数据传输超时30s

    /**
     * <p>功能描述:无参数的GET请求。</p>
     * <p>jl</p>
     * @param url
     * @since JDK1.8
     * <p>创建日期:2018/11/2 14:37。</p>
     * <p>更新日期:[日期YYYY-MM-DD][更改人姓名][变更描述]。</p>
     */
    public static String doGet(String url) {
        Args.notNull(url, "url");
        try {
            return Request.Get(url).connectTimeout(CONNECT_TIMEOUT).socketTimeout(SOCKET_TIMEOUT).execute().returnContent().asString(Consts.UTF_8);
        } catch (IOException e) {
            e.printStackTrace();
            LOGGER.error(e.getMessage(), e.toString());
        }
        return null;
    }

    /**
     * <p>功能描述:带参数的GET请求。</p>
     * <p>jl</p>
     * @param url
     * @param params
     * @since JDK1.8
     * <p>创建日期:2018/11/2 14:39。</p>
     * <p>更新日期:[日期YYYY-MM-DD][更改人姓名][变更描述]。</p>
     */
    public static String doGet(String url, Object params) {
        return executeGet(url, null, null, null, params);
    }

    /**
     * <p>功能描述:设置代理的 GET 请求。</p>
     * <p>jl</p>
     * @param url
     * @param hostName
     * @param port
     * @param schemeName
     * @param params
     * @since JDK1.8
     * <p>创建日期:2018/11/2 17:34。</p>
     * <p>更新日期:[日期YYYY-MM-DD][更改人姓名][变更描述]。</p>
     */
    public static String doGet(String url, String hostName, Integer port, String schemeName, Object params) {
        return executeGet(url, hostName, port, schemeName, params);
    }

    /**
     * <p>功能描述:执行 GET 请求。</p>
     * <p>jl</p>
     * @param url
     * @param hostName
     * @param port
     * @param schemeName
     * @param params
     * @since JDK1.8
     * <p>创建日期:2018/11/2 17:35。</p>
     * <p>更新日期:[日期YYYY-MM-DD][更改人姓名][变更描述]。</p>
     */
    private static String executeGet(String url, String hostName, Integer port, String schemeName, Object params) {
        if (StringUtils.isEmpty(url)) {
            return null;
        }
        url = buildGetParam(url, params);
        Request request = Request.Get(url).connectTimeout(CONNECT_TIMEOUT).socketTimeout(SOCKET_TIMEOUT);
        request = buildProxy(request, hostName, port, schemeName);
        try {
            return request.execute().returnContent().asString(Consts.UTF_8);
        } catch (IOException e) {
            e.printStackTrace();
            LOGGER.error(e.getMessage(), e.toString());
        }
        return null;
    }

    /**
     * <p>功能描述:构建 GET 参数。</p>
     * <p>jl</p>
     * @param url
     * @param params
     * @since JDK1.8
     * <p>创建日期:2018/11/2 16:52。</p>
     * <p>更新日期:[日期YYYY-MM-DD][更改人姓名][变更描述]。</p>
     */
    private static String buildGetParam(String url, Object params) {
        if (params != null) {
            //拼接参数
            url += "?" + URLEncodedUtilsPerfect.format(params, Consts.UTF_8);
        }
        return url;
    }

    /**
     * <p>功能描述:不带参数的 POST 请求。</p>
     * <p>jl</p>
     * @param url
     * @since JDK1.8
     * <p>创建日期:2018/11/2 17:36。</p>
     * <p>更新日期:[日期YYYY-MM-DD][更改人姓名][变更描述]。</p>
     */
    public static String doPost(String url) {
        return doPost(url, null, null, null, null, null);
    }

    /**
     * <p>功能描述:发送json格式的post请求。</p>
     * <p>jl</p>
     * @param url
     * @param jsonData
     * @since JDK1.8
     * <p>创建日期:2018/11/1 16:45。</p>
     * <p>更新日期:[日期YYYY-MM-DD][更改人姓名][变更描述]。</p>
     */
    public static String doPost(String url, String jsonData) {
        if (StringUtils.isEmpty(jsonData)) {
            return doPost(url);
        }
        Request request = Request.Post(url).connectTimeout(CONNECT_TIMEOUT).socketTimeout(SOCKET_TIMEOUT).bodyString(jsonData, ContentType.APPLICATION_JSON);
        try {
            return request.execute().returnContent().asString(Consts.UTF_8);
        } catch (IOException e) {
            e.printStackTrace();
            LOGGER.error(e.getMessage(), e.toString());
        }
        return null;
    }

    public static String doPost(String url, Object params) {
        return doPost(url, null, null, null, params, null);
    }

    public static void doPost(String url, Object params, List<File> files) {
        doPost(url, null, null, null, params, files);
    }

    public static String doPost(String url, String hostName, Integer port, String schemeName, Object params, List<File> files) {
        return executePost(url, hostName, port, schemeName, params, files);
    }

    private static String executePost(String url, String hostName, Integer port, String schemeName, Object params, List<File> files) {
        if (StringUtils.isEmpty(url)) {
            return null;
        }
        HttpEntity entity = buildPostParam(params, files);
        /**
         * Content type 'application/x-www-form-urlencoded'
         * 这是默认的不设置contentType时的请求头,那么在controller层接收的时候就要用 @RequestParam FirstProject firstProject
         * 这样的响应头来接收
         * 如果controller层用 @RequestBody FirstProject firstProject 这样的格式来接收,那么contentType应该设为 'application/json'
         * 传输数据的格式应该是json格式的,可以调用 doPost(String url, String jsonData)方法
         */
        Request request = Request.Post(url).connectTimeout(CONNECT_TIMEOUT).socketTimeout(SOCKET_TIMEOUT).body(entity);
        request = buildProxy(request, hostName, port, schemeName);
        try {
            return request.execute().returnContent().asString(Consts.UTF_8);
        } catch (IOException e) {
            e.printStackTrace();
            LOGGER.error(e.getMessage(), e.toString());
        }
        return null;
    }

    /**
     * 构建POST方法请求参数
     * @return
     */
    private static HttpEntity buildPostParam(Object params, List<File> files) {
        if(params == null && CollectionUtils.isEmpty(files)) {
            return null;
        }
        if(CollectionUtils.isNotEmpty(files)) {
            MultipartEntityBuilder builder = MultipartEntityBuilder.create();
            for (File file : files) {
                /**
                 * 在接收文件的响应头中默认是这样写的 @RequestParam List<MultipartFile> file
                 * 其实这样写默认接收响应头name为file的文件,即接收文件参数其实是这样的 @RequestParam("file") List<MultipartFile> file
                 * 所以addBinaryBody的name应该设为file,但是可根据自己接收参数的设置做相应修改
                 */
                builder.addBinaryBody("file", file, ContentType.APPLICATION_OCTET_STREAM, file.getName());
            }
            if (params != null) {
                if (params instanceof Map) {
                    Map map = (Map) params;
                    for (Object key : map.keySet()) {
                        if (key == null || map.get(key) == null) {
                            continue;
                        }
                        builder.addTextBody(key.toString(), map.get(key).toString(), ContentType.create("text/plain", Consts.UTF_8));
                    }
                } else if (params instanceof List) {
                    List list = (List) params;
                    if (list.get(0) instanceof NameValuePair) {
                        List<NameValuePair> nameValuePairs = list;
                        for (NameValuePair nameValuePair : nameValuePairs) {
                            //设置ContentType为UTF-8,默认为text/plain; charset=ISO-8859-1,传递中文参数会乱码
                            builder.addTextBody(nameValuePair.getName(), nameValuePair.getValue(), ContentType.create("text/plain", Consts.UTF_8));
                        }
                    }
                } else {    // 参数类型为 javaBean
                    // Object 转 Map 类型
                    Map map = new BeanMap(params);
                    for (Object key : map.keySet()) {
                        if (key == null || map.get(key) == null) {
                            continue;
                        }
                        builder.addTextBody(key.toString(), map.get(key).toString(), ContentType.create("text/plain", Consts.UTF_8));
                    }
                }

            }
            return builder.build();
        } else {
            return new UrlEncodedFormEntityPerfect(params, Consts.UTF_8);
        }
    }

    /**
     * 设置代理
     * @param request
     * @param hostName
     * @param port
     * @param schemeName
     * @return
     */
    private static Request buildProxy(Request request, String hostName, Integer port, String schemeName) {
        if(StringUtils.isNotEmpty(hostName) && port != null) {
            //设置代理
            if (StringUtils.isEmpty(schemeName)) {
                schemeName = HttpHost.DEFAULT_SCHEME_NAME;
            }
            request.viaProxy(new HttpHost(hostName, port, schemeName));
        }
        return request;
    }

}

URLEncodedUtils工具类完善

URLEncodedUtils工具类只提供了List<NameValuePair>集合的参数调用,所以我们继承该类,并完成Map和JavaBean的参数调用

package vip.coinbag.managemoneymatters.common.http;

import org.apache.commons.beanutils.BeanMap;
import org.apache.http.Consts;
import org.apache.http.NameValuePair;
import org.apache.http.client.utils.URLEncodedUtils;
import org.apache.http.util.Args;
import org.springframework.util.StringUtils;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.util.List;
import java.util.Map;

/**
 * <p>类描述:。</p>
 *
 * @author jl
 * @version v1.0.0.1。
 * @since JDK1.8。
 * <p>创建日期:2018/11/2 15:12。</p>
 */
public class URLEncodedUtilsPerfect extends URLEncodedUtils {
    private static final char QP_SEP_A = '&';
    private static final String NAME_VALUE_SEPARATOR = "=";

    /**
     * <p>功能描述:构造参数。</p>
     * <p>jl</p>
     * @param parameters
     * @param charset
     * @since JDK1.8
     * <p>创建日期:2018/11/2 17:09。</p>
     * <p>更新日期:[日期YYYY-MM-DD][更改人姓名][变更描述]。</p>
     */
    public static String format(
            final Object parameters,
            final Charset charset) {
        if (parameters == null) {
            return "";
        }
        if (parameters instanceof Map) {    // 参数类型为 Map
            Map map = (Map) parameters;
            return format(map, QP_SEP_A, charset != null ? charset : Consts.UTF_8);
        } else if ((parameters instanceof List)) {
            List list = (List) parameters;
            if (list.get(0) instanceof NameValuePair) { // 参数类型为 List<NameValuePair>
                List<NameValuePair> nameValuePairs = list;
                return format(nameValuePairs, charset != null ? charset : Consts.UTF_8);
            }
            return "";
        } else {    // 参数类型为 javaBean
            // Object 转 Map 类型
            Map map = new BeanMap(parameters);
            return format(map, QP_SEP_A, charset != null ? charset : Consts.UTF_8);
        }
    }

    /**
     * <p>功能描述:构造参数类型为 Map 的参数。</p>
     * <p>jl</p>
     * @param parameters
     * @param parameterSeparator
     * @param charset
     * @since JDK1.8
     * <p>创建日期:2018/11/2 17:23。</p>
     * <p>更新日期:[日期YYYY-MM-DD][更改人姓名][变更描述]。</p>
     */
    public static String format(
            final Map parameters,
            final char parameterSeparator,
            final Charset charset) {
        Args.notNull(parameters, "Parameters");
        final StringBuilder result = new StringBuilder();
        for (final Object key : parameters.keySet()) {
            try {
                final String encodedName = encodeFormFields(key, charset.toString());
                final String encodedValue = encodeFormFields(parameters.get(key), charset.toString());
                if (result.length() > 0) {
                    result.append(parameterSeparator);
                }
                if (StringUtils.isEmpty(encodedName) || StringUtils.isEmpty(encodedValue)) {
                    continue;
                }
                result.append(encodedName);
                if (encodedValue != null) {
                    result.append(NAME_VALUE_SEPARATOR);
                    result.append(encodedValue);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }

        }
        return result.toString();
    }

    /**
     * <p>功能描述:参数编码。</p>
     * <p>jl</p>
     * @param content
     * @param charset
     * @since JDK1.8
     * <p>创建日期:2018/11/2 17:22。</p>
     * <p>更新日期:[日期YYYY-MM-DD][更改人姓名][变更描述]。</p>
     */
    private static String encodeFormFields(final Object content, final String charset) throws UnsupportedEncodingException {
        if (content == null) {
            return null;
        }
        return URLEncoder.encode(content.toString(), charset);
    }

}

UrlEncodedFormEntity工具类完善

在构造post参数时同样只提供了List<NameValuePair>参数,所以跳过该类,直接继承该类的父类StringEntity,并结合上面的URLEncodedUtilsPerfect完成对Map和JavaBean的参数构造

package vip.coinbag.managemoneymatters.common.http;

import org.apache.http.Consts;
import org.apache.http.client.utils.URLEncodedUtils;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;

import java.nio.charset.Charset;

/**
 * <p>类描述:。</p>
 *
 * @author jl
 * @version v1.0.0.1。
 * @since JDK1.8。
 * <p>创建日期:2018/11/2 17:40。</p>
 */
public class UrlEncodedFormEntityPerfect extends StringEntity {

    public UrlEncodedFormEntityPerfect(final Object parameters, final Charset charset) {
        super(URLEncodedUtilsPerfect.format(parameters,
                charset != null ? charset : Consts.UTF_8),
                ContentType.create(URLEncodedUtils.CONTENT_TYPE, charset != null ? charset : Consts.UTF_8));
    }

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值