• HttpClient学习(Java)


    一、介绍

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

    我们可以通过这个HttpClient工具,在java代码中去构造和发送http请求

    了解http

    http的长短连接

    要搞清楚编程语言层面http client的使用,就得先对http协议有所了解。

    你应该知道http的transfer layer(传输层)其实是tcp协议,而tcp协议最关键的就是一次连接的建立到释放需要经过三次握手,四次挥手。

    那么如果你连续访问同一个服务器n次,就得建立n次连接,显然很耗费时间,用户使用体验不好,也没有必要。

    于是从HTTP1.1协议开始,有了所谓的长连接(persistent connection),而且客户端默认行为就是长连接(需要服务端也打开长连接才能实际生效),有了长连接,那么原来
    一次连接=一次请求+一次响应,现在可以一次连接=(一次请求+一次响应)*n,n>=1。

    tips:注意连接和请求是两个不同的概念。

    这样子对于连续n次请求同一服务器的场景来说,就比原来减少了n-1次连接,也就是减少了(3次握手+4次挥手)*(n-1)的时间。

    当然,在实际使用中,这里的请求次数n是有limitation的,即使你没有手动设置,其本身肯定也有一个默认值。
    除了请求数量上有限制外,一般还有时间上的限制,这里的时间限制包括连接的空闲时间最大存活时间(这两个概念是不同的)。上面我使用了连续请求这个词语,连续是个很抽象的概念,得使用量级去定义它,所以timeout就表明了两次连接时间间隔得在timeout内才算作连续。超过这个时间长连接会被释放掉。

    一般在请求头或者响应头通过这个字段定义:
    Keep-Alive: timeout=5, max=1000

    这表明长连接的空闲时间为5s,时间单位是秒。

    tips:在软件设计中,边界思想是很重要的。

    那客户端这一头是如何控制开启长短连接的呢?
    请求头的这个字段:Connection。

    Connection: close->禁止长连接
    Connection: keep-alive->使用长连接

    官网原话是:
    HTTP/1.1 defines the “close” connection option for the sender to signal that the
    connection will be closed after completion of the response.

    由于默认行为是长连接了(相当于默认值keep-alive),所以如果不想要长连接,那么需要显示指明这个请求头
    字段的值为close。

    有时候要小心一点的就是服务端没有打开长连接的支持(默认打开),虽然一般情况下不会有人这么做,但是原理还是要知道的。

    还有一点就是连接的关闭可以分为client主动关闭还是server端关闭,并不一定总是server端关闭的连接。

    连接池概念

    在apache http client中,连接是由连接管理对象来管理,有两种类型。
    一种是Simple connection manager(对应的是asicHttpClientConnectionManager.java),
    一种就是Pooling connection manager(对应的是PoolingHttpClientConnectionManager.java)。
    从名字上看就知道一个是一个http client对应一个connection,一个是一个http client对应一个connection pool,既然是pool,那么connection的数量就可能是n。

    tips:http client和connection是两个不同的概念。

    需要注意的是,如果没有明确的指定connnection manager,通过HttpClientBuilder.java创建http client的话默认会为你创建的是Pooling connection manager。

    根据实际需要选择,一般我都偏向于将http client作为单例使用。

    了解http 来自:https://zhuanlan.zhihu.com/p/341584129

    二、使用

    HttpClient的核心API:

    • HttpClient:Http客户端对象类型,使用该类型对象可发起Http请求。
    • HttpClients:可认为是构建器,可创建HttpClient对象。
    • CloseableHttpClient:实现类,实现了HttpClient接口。
    • HttpGet:Get方式请求类型。
    • HttpPost:Post方式请求类型。

    发送请求步骤

    1. 创建httpclient 对象
    2. 创建 httpclient 请求对象【实例】
      • 如果需要发送GET请求,创建HttpGet对象;如果需要发送POST请求,创建HttpPost对象。
      • 如果需要发送请求参数,可调用setEntity(HttpEntity entity)方法来设置请求参数;
    3. 调用httpclient 的execute方法发送请求

    三、代码案例

    采用的是阿里云的sdk-oss(包含了httpclient)

    <dependency>
        <groupId>com.aliyun.ossgroupId>
        <artifactId>aliyun-sdk-ossartifactId>
    dependency>
    
    
    • 1
    • 2
    • 3
    • 4
    • 5

    GET

     /**
         * 测试通过httpclient发送GET方式的请求
         */
        @Test
        public void testGET() throws Exception{
            //创建httpclient对象
            CloseableHttpClient httpClient = HttpClients.createDefault();
    
            //创建请求对象
            HttpGet httpGet = new HttpGet("http://localhost:8080/user/shop/status");
    
            //发送请求,接受响应结果
            CloseableHttpResponse response = httpClient.execute(httpGet);
    
            //获取服务端返回的状态码
            int statusCode = response.getStatusLine().getStatusCode();
            System.out.println("服务端返回的状态码为:" + statusCode);
    
            HttpEntity entity = response.getEntity();
            String body = EntityUtils.toString(entity);
            System.out.println("服务端返回的数据为:" + body);
    
            //关闭资源
            response.close();
            httpClient.close();
        }
     
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    POST

    /**
         * 测试通过httpclient发送POST方式的请求
         */
        @Test
        public void testPOST() throws Exception{
            // 创建httpclient对象
            CloseableHttpClient httpClient = HttpClients.createDefault();
    
            //创建请求对象
            HttpPost httpPost = new HttpPost("http://localhost:8080/admin/employee/login");
    
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("username","admin");
            jsonObject.put("password","123456");
    
            StringEntity entity = new StringEntity(jsonObject.toString());
            //指定请求编码方式
            entity.setContentEncoding("utf-8");
            //数据格式
            entity.setContentType("application/json");
            httpPost.setEntity(entity);
    
            //发送请求
            CloseableHttpResponse response = httpClient.execute(httpPost);
    
            //解析返回结果
            int statusCode = response.getStatusLine().getStatusCode();
            System.out.println("响应码为:" + statusCode);
    
            HttpEntity entity1 = response.getEntity();
            String body = EntityUtils.toString(entity1);
            System.out.println("响应数据为:" + body);
    
            //关闭资源
            response.close();
            httpClient.close();
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
  • 相关阅读:
    计算机毕业设计Java校园资料分享平台(系统+源码+mysql数据库+lw文档)
    下一代实时数据库:Apache Doris 【四】扩容缩容
    go底层TCP网络编程剖析
    mac m1 配置goland debbug
    SpringMVC学习---第二课
    【软件安装】Centos系统中安装docker容器(华为云HECS云耀服务器)
    Paramenter-Efficient Transfer Learning for NLP
    file-storage-sdk项目开发中的踩坑记录
    MetaAI的融合怪:BlenderBot
    布隆过滤器及其应用
  • 原文地址:https://blog.csdn.net/m0_60708917/article/details/134251482