http框架--基于httpclient 封装的http请求工具类

1. httpclient

1.1. 基本介绍

HttpClient是Apache Jakarta Common下的子项目,用来提供高效的、最新的、功能丰富的支持HTTP协议的客户端编程工具包,并且它支持HTTP协议最新的版本和建议。

HttpClient相比传统JDK自带的URLConnection,增加了易用性和灵活性,它不仅使客户端发送Http请求变得容易,而且也方便开发人员测试接口(基于Http协议的),提高了开发的效率,也方便提高代码的健壮性

注意:Commons HttpClient项目现在已经结束了,不再被开发。它已经被Apache HttpClient和HttpCore模块中的HttpComponents项目所取代,这些模块提供了更好的性能和更多的灵活性。详见:http://hc.apache.org/httpclient-legacy/index.html

1.2. 官网地址

官网地址
超文本传输协议(HTTP)可能是当今互联网上使用的最重要的协议。Web服务、支持网络的设备和网络计算的增长继续将HTTP协议的作用扩展到用户驱动的Web浏览器之外,同时增加了需要HTTP支持的应用程序的数量。
为扩展而设计的HttpComponents同时提供了对基本HTTP协议的健壮支持,任何构建感知HTTP的客户机和服务器应用程序(如web浏览器、web spider、HTTP代理、web服务传输库)的人都可能对它感兴趣

它由以下2个组件:

  • HttpCore是一组低级HTTP传输组件,可用于以最小的占用空间构建自定义客户端和服务器端HTTP服务。HttpCore支持两种I/O模型:基于经典Java I/O的阻塞I/O模型和基于Java NIO的非阻塞事件驱动I/O模型。
  • HttpClient是一个基于HttpCore的HTTP/1.1兼容的HTTP代理实现。它还为客户端身份验证、HTTP状态管理和HTTP连接管理提供可重用组件。HttpComponents Client是Commons HttpClient 3.x的继承者和替代者。强烈鼓励Commons HttpClient的用户升级

github地址
httpclient 4.5.x示例

1.3. 特性

4.5.x特性

  1. 基于标准、纯净的java语言。实现了Http1.0和Http1.1
  2. 以可扩展的面向对象的结构实现了Http全部的方法(GET, POST, PUT, DELETE, HEAD, OPTIONS, and TRACE)。
  3. 支持HTTPS协议。
  4. 通过Http代理建立透明的连接。
  5. 利用CONNECT方法通过Http代理建立隧道的https连接。
  6. Basic, Digest, NTLMv1, NTLMv2, NTLM2 Session, SNPNEGO/Kerberos认证方案。
  7. 插件式的自定义认证方案。
  8. 便携可靠的套接字工厂使它更容易的使用第三方解决方案。
  9. 连接管理器支持多线程应用。支持设置最大连接数,同时支持设置每个主机的最大连接数,发现并关闭过期的连接。
  10. 自动处理Set-Cookie中的Cookie。
  11. 插件式的自定义Cookie策略。
  12. Request的输出流可以避免流中内容直接缓冲到socket服务器。
  13. Response的输入流可以有效的从socket服务器直接读取相应内容。
  14. 在http1.0和http1.1中利用KeepAlive保持持久连接。
  15. 直接获取服务器发送的response code和 headers。
  16. 设置连接超时的能力。
  17. 实验性的支持http1.1 response caching。
  18. 源代码基于Apache License 可免费获取。

5.x 特性

2020年2月 httpclient从4.5直接升级了到5.0.

主要升级内容
1、支持HTTP/2
2、新的异步HTTP接口
3、重构reactor io模式,改进基于reactor 的NIO,使得性能和拓展性更好。
4、不论服务端是阻塞还是异步的实现,httpclient5均能支持服务端的过滤。例如横切协议(cross-cutting protocol)的握手,和用户认证授权。
5、支持reactive流的API
6、使用严格连接有限保证的方式重构连接池的实现。通过减少全局连接池的锁,连接池在高并发下获得更好的性能。
7、新的不严格连接有限保证连接池的实现。通过去除全局的连接池锁获得更高的性能。
8、更改包名
9、更改maven的groupId

2. 工具类源码

本文以httpclient 4.5.x, 将http请求的相同代码进行封装,简化代码,便捷使用。

2.1 使用示例

以第三方系统集成海豚调度系统为例,演示http请求工具类的使用

class HttpClientUtilsTest {
    public static void main(String[] args) throws Exception {
        String res = "";
        Map<String, String> params = Maps.newHashMap();
        params.put("userName", "admin");
        params.put("userPassword", "dolphinscheduler123");

        res = HttpClientUtils.post("http://172.25.xx.xx:12345/dolphinscheduler/login", params);
        printMsg("login res:%s", res);

        params.put("taskInstanceId", "703");
        params.put("skipLineNum", "0");
        params.put("limit", "1000");

        Map<String, String> headers = Maps.newHashMap();
        headers.put("token", "ca3e91749eee187fa9a797d92cf5cb6d");
        res = HttpClientUtils.get("http://172.25.xx.xx:12345/dolphinscheduler/log/detail", params, headers);
        printMsg("log detail res:%s", res);
    }

    private static void printMsg(String template, Object... args) {
        System.out.println(String.format(template, args));
    }
}

2.2. maven依赖

<dependency>
			<groupId>org.apache.httpcomponents</groupId>
			<artifactId>httpclient</artifactId>
			<version>4.5.13</version>
		</dependency>
		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<version>1.18.16</version>
		</dependency>
		<dependency>
			<groupId>org.apache.commons</groupId>
			<artifactId>commons-lang3</artifactId>
			<version>3.5</version>
		</dependency>
		<dependency>
			<groupId>com.google.guava</groupId>
			<artifactId>guava</artifactId>
			<version>28.0-jre</version>
		</dependency>
		<dependency>
			<groupId>com.alibaba</groupId>
			<artifactId>fastjson</artifactId>
			<version>1.2.76</version>
		</dependency>

2.3. 工具类源代码

import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.*;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpResponseException;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.config.ConnectionConfig;
import org.apache.http.config.SocketConfig;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.BasicCookieStore;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;

import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.charset.CodingErrorAction;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

@Slf4j
class HttpClientUtils {

    /**
     * 从连接池中获取连接的超时时间(单位:ms)
     */
    private static final int CONNECTION_REQUEST_TIMEOUT = 5000;

    /**
     * 与服务器连接的超时时间(单位:ms)
     */
    private static final int CONNECTION_TIMEOUT = 5000;

    /**
     * 从服务器获取响应数据的超时时间(单位:ms)
     */
    private static final int SOCKET_TIMEOUT = 10000;

    /**
     * 连接池的最大连接数
     */
    private static final int MAX_CONN_TOTAL = 10;

    /**
     * 每个路由上的最大连接数
     */
    private static final int MAX_CONN_PER_ROUTE = 5;

    /**
     * 用户代理配置
     */
    private static final String USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.67 Safari/537.36";

    public static final Charset UTF_8 = Charset.forName("UTF-8");

    /**
     * HttpClient对象
     */
    private static CloseableHttpClient httpClient = null;

    /**
     * Connection配置对象
     */
    private static ConnectionConfig connectionConfig = null;

    /**
     * Socket配置对象
     */
    private static SocketConfig socketConfig = null;

    /**
     * Request配置对象
     */
    private static RequestConfig requestConfig = null;

    /**
     * Cookie存储对象
     */
    private static BasicCookieStore cookieStore = null;


    static {
        init();
    }

    /**
     * 全局对象初始化
     */
    private static void init() {
        // 创建Connection配置对象
        connectionConfig = ConnectionConfig.custom()
                .setMalformedInputAction(CodingErrorAction.IGNORE)
                .setUnmappableInputAction(CodingErrorAction.IGNORE)
                .setCharset(UTF_8).build();

        // 创建Socket配置对象
        socketConfig = SocketConfig.custom().setTcpNoDelay(true).build();

        // 创建Request配置对象
        requestConfig = RequestConfig.custom()
                .setConnectionRequestTimeout(CONNECTION_REQUEST_TIMEOUT)
                .setConnectTimeout(CONNECTION_TIMEOUT)
                .setSocketTimeout(SOCKET_TIMEOUT)
                .build();

        // 创建Cookie存储对象(服务端返回的Cookie保存在CookieStore中,下次再访问时才会将CookieStore中的Cookie发送给服务端)
        cookieStore = new BasicCookieStore();

        // 创建HttpClient对象
        httpClient = HttpClients.custom()
                .setDefaultConnectionConfig(connectionConfig)
                .setDefaultSocketConfig(socketConfig)
                .setDefaultRequestConfig(requestConfig)
                .setDefaultCookieStore(cookieStore)
                .setUserAgent(USER_AGENT)
                .setMaxConnTotal(MAX_CONN_TOTAL)
                .setMaxConnPerRoute(MAX_CONN_PER_ROUTE)
                .build();
    }

    /**
     * post
     *
     * @param url
     * @param jsonParam
     * @return
     * @throws Exception
     */
    public static String post(String url, String jsonParam) throws IOException {
        String result = null;

        try {
            // 创建HttpPost
            HttpPost httpPost = new HttpPost(url);

            // 设置请求数据
            httpPost.setEntity(buildStringEntity(jsonParam, Consts.UTF_8));

            // 发送Post请求并得到响应结果
            HttpResponse httpResponse = httpClient.execute(httpPost);

            StatusLine statusLine = httpResponse.getStatusLine();
            HttpEntity httpEntity = httpResponse.getEntity();
            if (statusLine == null) {
                throw new ClientProtocolException("HttpResponse contains no StatusLine");
            }
            if (statusLine.getStatusCode() != HttpStatus.SC_OK) {
                throw new HttpResponseException(statusLine.getStatusCode(), statusLine.getReasonPhrase());
            }
            if (httpEntity == null) {
                throw new ClientProtocolException("HttpResponse contains no HttpEntity");
            }

            result = EntityUtils.toString(httpEntity, "UTF-8");
        } catch (Exception e) {
            log.error("throw exception " + e.getMessage(), e);
            throw e;
        }

        return result;
    }

    /**
     * post请求(用于key-value格式的参数)
     *
     * @param url
     * @param params
     * @return
     */
    public static String post(String url, Map<String, String> params) throws IOException {
        String result = "";
        try {
            // 实例化HTTP方法
            HttpPost httpPost = new HttpPost(url);
            //设置参数
            List<NameValuePair> nvps = new ArrayList<NameValuePair>();
            for (Iterator<String> iter = params.keySet().iterator(); iter.hasNext(); ) {
                String name = iter.next();
                String value = params.get(name);
                nvps.add(new BasicNameValuePair(name, value));
            }
            httpPost.setEntity(new UrlEncodedFormEntity(nvps, Consts.UTF_8));
            // 发送Post请求并得到响应结果
            HttpResponse httpResponse = httpClient.execute(httpPost);

            StatusLine statusLine = httpResponse.getStatusLine();
            HttpEntity httpEntity = httpResponse.getEntity();
            if (statusLine == null) {
                throw new ClientProtocolException("HttpResponse contains no StatusLine");
            }
            if (statusLine.getStatusCode() != HttpStatus.SC_OK) {
                throw new HttpResponseException(statusLine.getStatusCode(), statusLine.getReasonPhrase());
            }
            if (httpEntity == null) {
                throw new ClientProtocolException("HttpResponse contains no HttpEntity");
            }

            result = EntityUtils.toString(httpEntity, "UTF-8");
        } catch (Exception e) {
            log.error("throw exception " + e.getMessage(), e);
            throw e;
        }
        return result;
    }

    /**
     * get
     *
     * @param url
     * @param queryParams
     * @return
     * @throws Exception
     */
    public static String get(String url, Map<String, String> queryParams, Map<String, String> headers) throws Exception {
        String result = null;

        try {
            URIBuilder builder = new URIBuilder(url);
            for (Map.Entry<String, String> entry :queryParams.entrySet()){
                builder.setParameter(entry.getKey(), entry.getValue());
            }
            HttpGet httpGet = new HttpGet(builder.build());

            for (Map.Entry<String, String> entry : headers.entrySet()) {
                httpGet.addHeader(entry.getKey(), entry.getValue());
            }

            HttpResponse response = httpClient.execute(httpGet);
            StatusLine statusLine = response.getStatusLine();
            HttpEntity httpEntity = response.getEntity();
            if (statusLine == null) {
                throw new ClientProtocolException("HttpResponse contains no StatusLine");
            }
            if (statusLine.getStatusCode() != HttpStatus.SC_OK) {
                throw new HttpResponseException(statusLine.getStatusCode(), statusLine.getReasonPhrase());
            }
            if (httpEntity == null) {
                throw new ClientProtocolException("HttpResponse contains no HttpEntity");
            }

            result = EntityUtils.toString(httpEntity, "UTF-8");

        } catch (Exception e) {
            log.error("throw exception " + e.getMessage(), e);
            throw e;
        }
        return result;
    }

    /**
     * @param jsonParam
     * @param charset
     * @return
     */
    private static StringEntity buildStringEntity(String jsonParam, Charset charset) {
        /**
         * jsonParam"",否则无法创建StringEntity。
         * Json类型的请求体,必须传一个不为null的StringEntity给服务端。
         * 如果jsonData为null或""时,则进行特殊处理。
         */
        if (jsonParam == null || jsonParam.equals("")) {
            jsonParam = "{}";
        }
        StringEntity stringEntity = new StringEntity(jsonParam, ContentType.APPLICATION_JSON);
        if (charset != null) {
            stringEntity.setContentEncoding(charset.name());
        }
        return stringEntity;
    }
}
简介: 本框架是在Netroid的基础之上进行了封装,节省了其中配置的过程和一些不必要的操作 主要进行文本请求和图片请求,图片请求都进行了缓存(内存缓存和sd卡缓存)的封装,sd卡缓存时间可自行更改. 文本请求可传入解析的泛型clazz,即可返回解析后的clazz对象进行数据 操作,如果不需要进行数据解析,可通过另一种方式获取原生的string; 单图请求,单图请求可执行对本地asset文件夹,sd卡,http三种请求模式.只需传入相应的路径即可; 多图请求,多图请求主要是针对listview这种图文混排模式而生,能快速加载图片并实现缓存,不需要考虑 图片错位问题.只需传入相应的url即可完成全部功能. 使用说明: 1:在新创建的Manifest.xml中application中申明: <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" android:name="com.aqs.application.UApplication" > 并初始化Const.init();此处的初始化主要是对内存缓存,SD卡缓存大小,缓存时间等进行设置,如果不初始化,则按使用默认配置; 2:依赖HttpAqs-library或者jar包 3:通过公有方法进行网络请求,示例如下: >文本请求: >解析后的文本请求: HttpRequest.reqquest(int,String,Parse,Class){....}; >原生string文本请求: HttpRequest.getString(String,AqsString){...} >单张图片请求: HttpRequest.setImage(ImageView,String,int,int){...} >多张图片请求: 可使用AQSImageView控件来加载图片;特别是针对listview图文混排 实现方法: >在布局中添加 >在代码中 av.setImageUrl(url);
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

enjoy编程

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值