基于apache httpclient的http访问工具

本贴最后更新于 3470 天前,其中的信息可能已经天翻地覆

代码是对apache httpclient的简单封装,支持用户登录,调用方式如下

import org.junit.Test;

/**
 * @author niuhaipeng
 *
 * @date 2015年12月24日
 */
public class HttpClientTest {

    @Test
    public void testGet2String() {
        SimpleHttpClient client = new SimpleHttpClient();
        String url = "http://niuhp.com";
        while (true) {
            String content = client.doGet2String(url);
            System.out.println(content);
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

 

实现代码

import java.io.IOException;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;

import org.apache.http.Consts;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.AuthSchemes;
import org.apache.http.client.config.CookieSpecs;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.config.RequestConfig.Builder;
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.methods.HttpRequestBase;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.ContentType;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;

import com.niuhp.toolbox.logadapter.LogX;
import com.niuhp.toolbox.util.IoUtil;

/**
 * @author niuhaipeng
 *
 * @date 2015年12月17日
 */
public class SimpleHttpClient {

    private HttpClient httpClient;
    private Object lockObj = new Object();

    private int connectionRequestTimeout = 10000;
    private int connectTimeout = 10000;
    private int defaultMaxPerRoute = 20;
    private int maxTotal = 100;
    /**
     * 请求自动关闭时间,防止调用者长期持有请求
     */
    private long autoCloseTimeout = 3000;
    private final ExecutorService executorService = Executors.newFixedThreadPool(50);

    private void checkInit(boolean https) {
        if (httpClient != null) {
            return;
        }
        synchronized (lockObj) {
            if (httpClient != null) {
                return;
            }
            Builder builder = RequestConfig.custom();
            builder.setCookieSpec(CookieSpecs.STANDARD_STRICT);
            builder.setConnectionRequestTimeout(connectionRequestTimeout);
            builder.setConnectTimeout(connectTimeout);
            if (https) {
                builder.setExpectContinueEnabled(true);
                Collection<String> targetPreferredAuthSchemes = Arrays.asList(AuthSchemes.NTLM, AuthSchemes.DIGEST);
                builder.setTargetPreferredAuthSchemes(targetPreferredAuthSchemes);
                Collection<String> proxyPreferredAuthSchemes = Arrays.asList(AuthSchemes.BASIC);
                builder.setProxyPreferredAuthSchemes(proxyPreferredAuthSchemes);
            }
            RequestConfig config = builder.build();

            HttpClientBuilder httpClientBuilder = HttpClients.custom();
            httpClientBuilder.setDefaultRequestConfig(config);
            if (https) {
                RegistryBuilder<ConnectionSocketFactory> registryBuilder = RegistryBuilder.create();
                registryBuilder.register("http", PlainConnectionSocketFactory.INSTANCE);
                TrustManager trustManager = new CustomizedX509TrustManager();

                try {
                    SSLContext context = SSLContext.getInstance("TLS");
                    context.init(null, new TrustManager[] { trustManager }, null);
                    ConnectionSocketFactory connectionSocketFactory = new SSLConnectionSocketFactory(context,
                            NoopHostnameVerifier.INSTANCE);
                    registryBuilder.register("https", connectionSocketFactory);
                } catch (Exception e) {
                    LogX.getLogX(getClass()).error("register connectionSocketFactory error", e);
                }
                Registry<ConnectionSocketFactory> registry = registryBuilder.build();
                PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager(registry);
                connManager.setMaxTotal(maxTotal);
                connManager.setDefaultMaxPerRoute(defaultMaxPerRoute);
                httpClientBuilder.setConnectionManager(connManager);
            }
            httpClient = httpClientBuilder.build();
        }
    }

    public String doGet2String(String url) {
        return doGet2String(url, null);
    }

    public String doGet2String(String url, Map<String, String> paraMap) {
        HttpResponse reponse = doGet(url, paraMap);
        return getContent(reponse);
    }

    public HttpResponse doGet(String url, Map<String, String> paraMap) {
        StringBuilder urlBuilder = new StringBuilder();
        urlBuilder.append(url);
        if (paraMap != null && !paraMap.isEmpty()) {
            urlBuilder.append("?");
            Set<String> keys = paraMap.keySet();
            Iterator<String> it = keys.iterator();
            String key = it.next();
            urlBuilder.append(key).append("=").append(paraMap.get(key));
            while (it.hasNext()) {
                key = it.next();
                urlBuilder.append("&").append(key).append("=").append(paraMap.get(key));
            }
        }
        return doGet(urlBuilder.toString());
    }

    public HttpResponse doGet(String url) {
        boolean https = url != null && url.startsWith("https");
        checkInit(https);
        HttpGet get = new HttpGet(url);
        return doRequest(httpClient, get);
    }

    public String doPost2String(String url) {
        return doPost2String(url, null);
    }

    public String doPost2String(String url, Map<String, String> paraMap) {
        HttpResponse response = doPost(url, paraMap);
        return getContent(response);
    }

    public HttpResponse doPost(String url) {
        return doPost(url, null);
    }

    public HttpResponse doPost(String url, Map<String, String> paraMap) {
        boolean https = url != null && url.startsWith("https");
        checkInit(https);
        HttpPost post = new HttpPost(url);
        List<NameValuePair> values = toValues(paraMap);
        if (values != null && !values.isEmpty()) {
            HttpEntity entity = new UrlEncodedFormEntity(values, Consts.UTF_8);
            post.setEntity(entity);
        }
        return doRequest(httpClient, post);
    }

    private void autoClose(HttpUriRequest request, HttpResponse reponse) {
        Runnable runnable = new Runnable() {

            @Override
            public void run() {
                try {
                    Thread.sleep(autoCloseTimeout);
                } catch (InterruptedException e) {
                    LogX.getLogX(getClass()).error("sleep error", e);
                }
                if (request instanceof HttpRequestBase) {
                    HttpRequestBase httpRequestBase = (HttpRequestBase) request;
                    httpRequestBase.releaseConnection();
                }
                IoUtil.closeHttpResponse(reponse);
                LogX.getLogX(getClass()).info(String.format("autoClose request[%s] and reponse[%s]", request, reponse));
            }
        };

        executorService.execute(runnable);
    }

    private HttpResponse doRequest(HttpClient httpClient, HttpUriRequest httpRequest) {
        synchronized (httpClient) {
            try {
                HttpResponse response = httpClient.execute(httpRequest);
                autoClose(httpRequest, response);
                return response;
            } catch (Exception e) {
                LogX.getLogX(getClass()).error("execute error", e);
            }
        }
        return null;
    }

    public void closeHttpClient() {
        IoUtil.closeHttpClient(httpClient);
    }

    private static List<NameValuePair> toValues(Map<String, String> paraMap) {
        if (paraMap == null) {
            return null;
        }
        List<NameValuePair> values = new ArrayList<NameValuePair>(paraMap.size());
        Set<String> keys = paraMap.keySet();
        for (String key : keys) {
            NameValuePair pair = new BasicNameValuePair(key, paraMap.get(key));
            values.add(pair);
        }
        return values;
    }

    private String getContent(HttpResponse response) {
        if (response == null) {
            return null;
        }
        HttpEntity httpEntity = response.getEntity();
        if (httpEntity == null) {
            return null;
        }
        String content = null;

        try {
            Charset charset = ContentType.getOrDefault(httpEntity).getCharset();
            content = EntityUtils.toString(httpEntity, charset);
        } catch (IOException e) {
            LogX.getLogX(getClass()).error("getContent error", e);
        } finally {
            IoUtil.closeHttpResponse(response);
        }
        return content;
    }

    public int getConnectionRequestTimeout() {
        return connectionRequestTimeout;
    }

    public void setConnectionRequestTimeout(int connectionRequestTimeout) {
        this.connectionRequestTimeout = connectionRequestTimeout;
    }

    public int getConnectTimeout() {
        return connectTimeout;
    }

    public void setConnectTimeout(int connectTimeout) {
        this.connectTimeout = connectTimeout;
    }

    public int getDefaultMaxPerRoute() {
        return defaultMaxPerRoute;
    }

    public void setDefaultMaxPerRoute(int defaultMaxPerRoute) {
        this.defaultMaxPerRoute = defaultMaxPerRoute;
    }

    public int getMaxTotal() {
        return maxTotal;
    }

    public void setMaxTotal(int maxTotal) {
        this.maxTotal = maxTotal;
    }

    public long getAutoCloseTimeout() {
        return autoCloseTimeout;
    }

    public void setAutoCloseTimeout(long autoCloseTimeout) {
        if (autoCloseTimeout <= 0 || autoCloseTimeout > 5000) {
            LogX.getLogX(getClass()).warn(String.format("autoCloseTimeout must be from %s to %s", 0, 5000));
            return;
        }
        this.autoCloseTimeout = autoCloseTimeout;
    }

}

 

import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

import javax.net.ssl.X509TrustManager;

/**
 * @author niuhaipeng
 *
 * @date 2015年12月17日
 */
public class CustomizedX509TrustManager implements X509TrustManager {

    @Override
    public void checkClientTrusted(X509Certificate[] arg0, String arg1)
            throws CertificateException {

    }

    @Override
    public void checkServerTrusted(X509Certificate[] arg0, String arg1)
            throws CertificateException {

    }

    @Override
    public X509Certificate[] getAcceptedIssuers() {
        return null;
    }

}

maven配置

        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
            <version>4.5.1</version>
        </dependency>

本文代码均可以从github下载地址 https://github.com/niuhp/toolbox

  • HttpClient
    8 引用 • 10 回帖
  • 登录
    17 引用 • 133 回帖
  • Java

    Java 是一种可以撰写跨平台应用软件的面向对象的程序设计语言,是由 Sun Microsystems 公司于 1995 年 5 月推出的。Java 技术具有卓越的通用性、高效性、平台移植性和安全性。

    3201 引用 • 8217 回帖 • 1 关注
  • Apache
    27 引用 • 35 回帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...

推荐标签 标签

  • Ngui

    Ngui 是一个 GUI 的排版显示引擎和跨平台的 GUI 应用程序开发框架,基于
    Node.js / OpenGL。目标是在此基础上开发 GUI 应用程序可拥有开发 WEB 应用般简单与速度同时兼顾 Native 应用程序的性能与体验。

    7 引用 • 9 回帖 • 403 关注
  • 小薇

    小薇是一个用 Java 写的 QQ 聊天机器人 Web 服务,可以用于社群互动。

    由于 Smart QQ 从 2019 年 1 月 1 日起停止服务,所以该项目也已经停止维护了!

    35 引用 • 468 回帖 • 765 关注
  • RESTful

    一种软件架构设计风格而不是标准,提供了一组设计原则和约束条件,主要用于客户端和服务器交互类的软件。基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制。

    30 引用 • 114 回帖 • 1 关注
  • 深度学习

    深度学习(Deep Learning)是机器学习的分支,是一种试图使用包含复杂结构或由多重非线性变换构成的多个处理层对数据进行高层抽象的算法。

    43 引用 • 44 回帖
  • GitBook

    GitBook 使您的团队可以轻松编写和维护高质量的文档。 分享知识,提高团队的工作效率,让用户满意。

    3 引用 • 8 回帖
  • 生活

    生活是指人类生存过程中的各项活动的总和,范畴较广,一般指为幸福的意义而存在。生活实际上是对人生的一种诠释。生活包括人类在社会中与自己息息相关的日常活动和心理影射。

    230 引用 • 1432 回帖
  • 心情

    心是产生任何想法的源泉,心本体会陷入到对自己本体不能理解的状态中,因为心能产生任何想法,不能分出对错,不能分出自己。

    59 引用 • 369 回帖
  • Jenkins

    Jenkins 是一套开源的持续集成工具。它提供了非常丰富的插件,让构建、部署、自动化集成项目变得简单易用。

    54 引用 • 37 回帖
  • 思源笔记

    思源笔记是一款隐私优先的个人知识管理系统,支持完全离线使用,同时也支持端到端加密同步。

    融合块、大纲和双向链接,重构你的思维。

    26103 引用 • 108377 回帖
  • SendCloud

    SendCloud 由搜狐武汉研发中心孵化的项目,是致力于为开发者提供高质量的触发邮件服务的云端邮件发送平台,为开发者提供便利的 API 接口来调用服务,让邮件准确迅速到达用户收件箱并获得强大的追踪数据。

    2 引用 • 8 回帖 • 507 关注
  • SSL

    SSL(Secure Sockets Layer 安全套接层),及其继任者传输层安全(Transport Layer Security,TLS)是为网络通信提供安全及数据完整性的一种安全协议。TLS 与 SSL 在传输层对网络连接进行加密。

    70 引用 • 193 回帖 • 413 关注
  • 锤子科技

    锤子科技(Smartisan)成立于 2012 年 5 月,是一家制造移动互联网终端设备的公司,公司的使命是用完美主义的工匠精神,打造用户体验一流的数码消费类产品(智能手机为主),改善人们的生活质量。

    4 引用 • 31 回帖 • 3 关注
  • GitHub

    GitHub 于 2008 年上线,目前,除了 Git 代码仓库托管及基本的 Web 管理界面以外,还提供了订阅、讨论组、文本渲染、在线文件编辑器、协作图谱(报表)、代码片段分享(Gist)等功能。正因为这些功能所提供的便利,又经过长期的积累,GitHub 的用户活跃度很高,在开源世界里享有深远的声望,并形成了社交化编程文化(Social Coding)。

    209 引用 • 2040 回帖
  • Swift

    Swift 是苹果于 2014 年 WWDC(苹果开发者大会)发布的开发语言,可与 Objective-C 共同运行于 Mac OS 和 iOS 平台,用于搭建基于苹果平台的应用程序。

    34 引用 • 37 回帖 • 554 关注
  • Hexo

    Hexo 是一款快速、简洁且高效的博客框架,使用 Node.js 编写。

    22 引用 • 148 回帖 • 6 关注
  • InfluxDB

    InfluxDB 是一个开源的没有外部依赖的时间序列数据库。适用于记录度量,事件及实时分析。

    2 引用 • 99 关注
  • 友情链接

    确认过眼神后的灵魂连接,站在链在!

    24 引用 • 373 回帖
  • danl
    175 关注
  • RabbitMQ

    RabbitMQ 是一个开源的 AMQP 实现,服务器端用 Erlang 语言编写,支持多种语言客户端,如:Python、Ruby、.NET、Java、C、PHP、ActionScript 等。用于在分布式系统中存储转发消息,在易用性、扩展性、高可用性等方面表现不俗。

    49 引用 • 60 回帖 • 351 关注
  • ZooKeeper

    ZooKeeper 是一个分布式的,开放源码的分布式应用程序协调服务,是 Google 的 Chubby 一个开源的实现,是 Hadoop 和 HBase 的重要组件。它是一个为分布式应用提供一致性服务的软件,提供的功能包括:配置维护、域名服务、分布式同步、组服务等。

    60 引用 • 29 回帖 • 8 关注
  • Notion

    Notion - The all-in-one workspace for your notes, tasks, wikis, and databases.

    10 引用 • 77 回帖 • 1 关注
  • WiFiDog

    WiFiDog 是一套开源的无线热点认证管理工具,主要功能包括:位置相关的内容递送;用户认证和授权;集中式网络监控。

    1 引用 • 7 回帖 • 612 关注
  • 小说

    小说是以刻画人物形象为中心,通过完整的故事情节和环境描写来反映社会生活的文学体裁。

    32 引用 • 108 回帖
  • 旅游

    希望你我能在旅途中找到人生的下一站。

    98 引用 • 903 回帖
  • DevOps

    DevOps(Development 和 Operations 的组合词)是一组过程、方法与系统的统称,用于促进开发(应用程序/软件工程)、技术运营和质量保障(QA)部门之间的沟通、协作与整合。

    59 引用 • 25 回帖 • 2 关注
  • Firefox

    Mozilla Firefox 中文俗称“火狐”(正式缩写为 Fx 或 fx,非正式缩写为 FF),是一个开源的网页浏览器,使用 Gecko 排版引擎,支持多种操作系统,如 Windows、OSX 及 Linux 等。

    7 引用 • 30 回帖 • 380 关注
  • 叶归
    12 引用 • 56 回帖 • 22 关注