java处理http请求之Apache httpClient入门教程

说明

本文示例代码基于 4.5.13 版本

转载请注明出处:https://www.cnblogs.com/qnlcy/p/15378446.html

一、项目介绍

Apache 提供用来做http请求的项目有两个,3.x 版本的项目叫做 The Commons HttpClient

它一开始是 Apache Jakarta Common 下的子项目,后来独立出去了,现在这个项目已经结束了它的生命周期,不再开发和维护。

取而代之的是 4.x 版本的 Apache Httpcomponents 项目,它包括 HttpClientHttpCore 两大模块,能提供更好的性能和更大的灵活性。

二、项目模块

Apache Httpcomponents 项目包括 HttpClientHttpCore 两大模块,其中, HttpCore 是一套HTTP协议实现包。而 HttpClient 是基于HttpCore的一套客户端。

三、使用方式

使用 Httpclient 需要经过如下步骤

  1. 创建 HttpClient
  2. 创建 http 请求,如 HttpGetHttpPost
  3. 添加请求参数
  4. 添加请求设置,如超时等
  5. 使用 HttpClient 执行 http 请求
  6. 读取返回内容并释放连接

3.1 创建 HttpClient

3.1.1 创建默认客户端:

    CloseableHttpClient httpclient = HttpClients.createDefault();

一些重要的默认配置:

  • 默认连接池大小10,每域名最大连接5
  • 连接池中连接存活时间 connTimeToLive = -1 ,默认单位为毫秒,默认连接不失效
  • 域名验证器为 DefaultHostnameVerifier , 会验证域名
  • SSL 上下文为 SSLContext.getInstance("TLS"),没有使用密钥管理器(KeyManager)和信任管理器(TrustManager)

3.1.2 自定义客户端

  • 失败不重试
    CloseableHttpClient client = HttpClients.custom().setRetryHandler((e, i, c) -> false).build();
  • 自定义连接池
 //设置自定义连接池
    @Test
    public void customConnectionPool() throws Exception {
        //1.创建 https 需要的 SslContext 相关内容
        //1.1 创建 SslContext
        KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
        ks.load(new FileInputStream("证书文件"), "密码".toCharArray());
        SSLContext sslContext = SSLContexts.custom().loadTrustMaterial(TrustAllStrategy.INSTANCE)
                .loadKeyMaterial(ks, "证书密码".toCharArray()).build();
        //1.2 创建 SSLConnectionSocketFactory
        SSLConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory(sslContext, new String[]{"SSLv3", "TLSv1.1", "TLSv1.2"}, null,
                NoopHostnameVerifier.INSTANCE);

        //2.创建连接池
        //2.1 构建协议 registry
        Registry registry = RegistryBuilder.create()
                .register("http", PlainConnectionSocketFactory.getSocketFactory())
                .register("https", sslConnectionSocketFactory)
                .build();
        PoolingHttpClientConnectionManager poolingHttpClientConnectionManager = new PoolingHttpClientConnectionManager(registry);
        //3.连接池针对所有连接、每域名的连接的数量设置
        poolingHttpClientConnectionManager.setMaxTotal(100);
        poolingHttpClientConnectionManager.setDefaultMaxPerRoute(20);

        //4.创建client
        CloseableHttpClient client =
        HttpClients.custom().setConnectionManager(poolingHttpClientConnectionManager).build();
    }

3.2 创建 Http 请求

创建 HttpGetHttpPost 请求

    @Test
    public void getAndPost(){
        //1.创建get请求
        HttpGet get = new HttpGet("https://www.baidu.com");

        //2.创建post请求
        HttpPost post = new HttpPost("https://www.baidu.com");

        //3.其他如 HttpPut、HttpOptions、HttpTrace、HttpDelete、HttpPatch
    }

3.3 添加请求参数

    @Test
    public void addParams() throws IOException {
        HttpPost post = new HttpPost("https://www.baidu.com");
        //1.底层流,基础参数
        BasicHttpEntity basicHttpEntity = new BasicHttpEntity();
        //1.1添加参数内容
        InputStream bis = new ByteArrayInputStream("参数".getBytes());
        basicHttpEntity.setContent(bis);
        //1.2设置内容长度
        basicHttpEntity.setContentLength(bis.available());
        //1.3取消分块发送
        basicHttpEntity.setChunked(false);
        post.setEntity(basicHttpEntity);

        //2.字节码类型参数
        HttpEntity entity = new ByteArrayEntity("name=zhangsan&age=100".getBytes());
        post.setEntity(entity);

        //3.字符串类型参数
        entity = new StringEntity("name=zhangsan&age=100");
        post.setEntity(entity);

        //4.流式参数,用法与BasicHttpEntity类似,内容和长度严格匹配
        entity = new InputStreamEntity(bis,bis.available());
        post.setEntity(entity);

        //5.文件类型参数
        entity = new FileEntity(new File("上传文件"));
        post.setEntity(entity);

        //6.添加请求头
        post.addHeader("Content-Type","text/html;charset=UTF-8");

        Header contentType = new BasicHeader("Content-Type","text/html;charset=UTF-8");
        post.addHeader(contentType);

        Header host = new BasicHeader("Host","www.baidu.com");
        post.setHeaders(new Header[]{contentType,host});

    }

3.4 添加请求设置

    @Test
    public void requestConfig(){
        //1.配置RequestConfig
        RequestConfig requestConfig = RequestConfig.custom()
        .setConnectionRequestTimeout(10000) //从连接池获取可用连接的超时时间,单位毫秒
        .setSocketTimeout(5000) //请求获取数据的超时时间
        .setConnectTimeout(4000) //连接超时时间
        .build();
        HttpPost post = new HttpPost("https://www.baidu.com");
        //2.设置到post请求当中
        post.setConfig(requestConfig);

        //也可以当作默认值,设置到client当中,此client都会按这个超时处理
        CloseableHttpClient client = HttpClients.custom().setDefaultRequestConfig(requestConfig).build();
    }

3.4.1 超时时间说明

超时类型 说明 connectionTimeout 连接建立时间,即3次握手时间,默认值-1 socketTimeout 连接后,数据传输过程中 数据包之间间隔

的最大时间,默认值-1 connectionRequestTimeout 从连接池获取连接的超时时间,默认值-1

java处理http请求之Apache httpClient入门教程

注意: socketTimeoutconnectionRequestTimeout 如果不设置,请求会阻塞。
但是 connectionTimeout 的情况有所不同,它依赖于各平台的 socket 超时时间设置。
windows 10 实测为 20s, linux 平台则不定,它会按 /proc/sys/net/ipv4/tcp_syn_retries 中配置的次数重试,一般为3s\7s\15s\31s\63s递增
另外,即使 java 程序返回了超时结果,但是linux服务器依旧在执行重试直到服务器端超时,为了提高资源利用率,可以手动关闭

关于 linux socket 超时的问题,请参阅 无毁的湖光-Al从linux源码看socket(tcp)的timeout

3.5 执行 http 请求

执行 http 请求比较简单,直接调用 execute() 方法即可

    @Test
    public void execute(){
        CloseableHttpClient client = HttpClients.createDefault();
        try {
            client.execute(new HttpPost("https://www.baidu.com"));
            client.execute(new HttpGet("https://www.baidu.com"));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

3.6 读取返回内容并释放连接

服务器返回结果被封装到 HttpResponse 对象里,我们可以从这里拿到我们想要的返回结果

    @Test
    public void getResponse() {
        CloseableHttpClient client = HttpClients.createDefault();
        CloseableHttpResponse httpResponse = null;
        final HttpGet httpGet = new HttpGet("https://www.baidu.com");
        try {
            httpResponse = client.execute(httpGet);
            //1.获取返回状态
            System.out.println(httpResponse.getStatusLine().getStatusCode());
            //2.获取返回头信息
            Header[] headers = httpResponse.getAllHeaders();
            for (Header header : headers) {
                System.out.println(header.getName() + ":" + header.getValue());
            }
            //3.获取返回消息体
            HttpEntity entity = httpResponse.getEntity();
            if(null != entity){
                //3.1 得到返回结果并关闭流,与下面的只能执行一个,因为流只能读取一次
                String content = EntityUtils.toString(entity);
                System.out.println(content);
                //3.2 得到返回结果并关闭流,与上面的只能执行一个
//              byte[] contents = EntityUtils.toByteArray(entity);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (null != httpResponse) {
                //4.归还连接到连接池
                try {
                    httpResponse.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            //如果复用 httpGet ,则重置其状态使其可以重复使用
            httpGet.releaseConnection();
        }

        //只在应用关闭的时候关闭client
        try {
            client.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

Original: https://www.cnblogs.com/qnlcy/p/15378446.html
Author: 去哪里吃鱼
Title: java处理http请求之Apache httpClient入门教程

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/577906/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • Linux之Keepalived高可用

    一、高可用介绍 一般是指2台机器启动着完全相同的业务系统,当有一台机器down机了,另外一台服务器就能快速的接管,对于访问的用户是无感知的。 硬件通常使用:F5 软件通常使用:Ke…

    Linux 2023年5月27日
    0106
  • Zabbix-企业级监控系统

    Zabbix-企业级监控系统 Zabbix 手册-官网 1.Zabbix简介 Zabbix 是一款监控网络的众多参数以及服务器、虚拟机、应用程序、服务、数据库、网站、云等的健康和完…

    Linux 2023年6月13日
    075
  • LVS+KeepAlived高可用部署架构

    1 构建高可用集群 1.1 什么是高可用集群 高可用集群(High Availability Cluster,简称HA Cluster),是指以减少服务中断时间为目的得服务器集群技…

    Linux 2023年6月13日
    080
  • JVM的监控

    JVM的监控 Table of Contents *一、jvm常见监控工具&指令 * 1、 jps:jvm进程状况工具 * 2、jstat: jvm统计信息监控工具 * 3…

    Linux 2023年6月13日
    0126
  • 命名空间、作用域、LEGB法则、垃圾回收机制

    一、命名空间、作用域、LEGB法则、 1.命名空间和作用域 :   命名&#x7A7…

    Linux 2023年6月8日
    083
  • Linux安装mysql8.0

    MySQL 配置MySQL8安装源 sudo rpm -Uvh https://dev.mysql.com/get/mysql80-community-release-el7-3….

    Linux 2023年6月6日
    090
  • 【小记】Linux find 配合 rm 命令安全批量删除文件

    可以先运行: find . -name "*.log" 确认通配符匹配到的文件是你想删除的文件。再命令执行删除: find . -name "*.lo…

    Linux 2023年6月13日
    092
  • [ Shell ] 通过 Shell 脚本导出 GDSII/OASIS 文件

    常见的集成电路版图数据库文件格式有 GDSII 和 OASIS,virtuoso 提供了下面两个工具,可以用来通过命令行导出版图数据。 strmout (导出为 GDSII 格式)…

    Linux 2023年6月7日
    0125
  • ASCLL 字符码

    信息在计算机上是用二进制数表示的,这种表示法让人很难理解。因此,计算机上都配有输入和输出设备,这些设备的主要目的就是以一种人类可阅读的形式将信息在这些设备上显示出来供人阅读理解。为…

    Linux 2023年6月7日
    097
  • CentOS——Redis消息订阅发布

    作用: 发布订阅类似于信息管道,用来进行系统之间消息解耦。类似于mq,rebbitmq,rocketmq,kafka,activemq 主要有消息发布者和消息订阅者。 比如:订单支…

    Linux 2023年5月28日
    099
  • shell中 $() $(()) $[] ${} $[[]] 区别

    $( ) 与 (反引号) 在 bash shell &#x4E…

    Linux 2023年5月28日
    095
  • c++智能指针的使用,shared_ptr,unique_ptr,weak_ptr

    c++智能指针的使用 官方参考 普通指针的烦恼:内存泄漏,多次释放,提前释放 智能指针 负责自动释放所指向的对象。 三种智能指针 shared_ptr,unique_ptr,wea…

    Linux 2023年6月14日
    0128
  • 一篇文章扒掉“桥梁Handler”的底裤

    Android跨进程要掌握的是Binder, 而同一进程中最重要的应该就是Handler 消息通信机制了。我这么说,大家不知道是否认同,如果认同,还希望能给一个关注哈。 什么是Ha…

    Linux 2023年6月13日
    095
  • DML

    用来对数据库中的表的数据进行增删改 添加数据 给指定列添加数据 insert into <表名> (&#x5217;&#x540D;1, &#x…

    Linux 2023年6月7日
    089
  • DEX文件解析–7、类及其类数据解析(完结篇)

    一、前言 前置技能链接:DEX文件解析—1、dex文件头解析DEX文件解析—2、Dex文件checksum(校验和)解析DEX文件解析–3、de…

    Linux 2023年6月8日
    081
  • 网络安全中常用浏览器插件、拓展

    引言 现在的火狐、Edge( Chromium内核)、Chrome等浏览器带有插件、拓展(Plugin)的功能。这些插件中有的可以过滤广告,有的提供便捷的翻译,有的提供JavaSc…

    Linux 2023年6月6日
    089
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球