org.apache.httpcomponents下的httpclient使用

本文介绍如何使用 HTTPClient 4.5 版本发起 HTTP 请求,并演示了 GET 和 POST 请求的具体实现方法,包括参数传递、响应处理等。

一、概述

      这里只针对4.5的版本进行介绍。

      在项目中经常有需要发送http请求的场景,httpclient很好的解决了这个问题,而且非常易用。

maven依赖
<dependency>
        <groupId>org.apache.httpcomponents</groupId>
        <artifactId>httpclient</artifactId>
        <version>4.5</version>
    </dependency>
一个最简单的demo
// 创建客户端
        CloseableHttpClient httpclient = HttpClients.createDefault();

        //创建一个get请求
        HttpGet httpget = new HttpGet("https://api.douban.com/v2/book/1220562");
        CloseableHttpResponse response = null;
        try {
            //发送请求并获取返回结果
            response = httpclient.execute(httpget);

            if(HttpStatus.SC_OK == response.getStatusLine().getStatusCode()){//判断状态码
                HttpEntity httpEntity = response.getEntity(); //获取返回body
                String result = EntityUtils.toString(httpEntity,"UTF-8");// 转成string
                System.out.println("result:"+result);
            }
        } catch(IOException ioe){

        }finally {
            try{
                if(response != null){
                    response.close(); //释放连接
                }
            }catch(Exception e){}
            try{
                if(httpclient != null){
                    httpclient.close();//关闭客户端
                }
            }catch(Exception e){}
        }
运行结果

上面是一个非常简单的示例,创建客户端-->创建请求-->发送请求并获取返回结果-->处理返回结果-->关闭连接,流程很清晰。

在生产环境中,我们是不会直接使用

CloseableHttpClient httpclient = HttpClients.createDefault();

这种方式来创建httpclient的。因为这种方式忽略了许多配置,例如最大连接数,请求配置,很有可能导致生产环境出问题。在生产环境中,我们采用自定义的方式创建客户端,例如:

RequestConfig requestConfig = RequestConfig //请求设置
                    .custom()
                    .setConnectionRequestTimeout(ConnectionRequestTimeout) //从连接池获取连接超时时间
                    .setConnectTimeout(ConnectionTimeout) //连接超时时间
                    .setSocketTimeout(SocketTimeout).build(); //套接字超时时间

            HttpClientBuilder builder = HttpClients.custom()
                    .setDefaultRequestConfig(requestConfig)
                    .setMaxConnTotal(MaxConnTotal); //设置最大连接数

            httpClient = builder.build();

这是一个比较通用的httpclient。其实还有很多配置没有列出来,可以参考官网。

get请求

最简单的get请求如下所示:

 //创建一个get请求
        HttpGet httpget = new HttpGet("https://api.douban.com/v2/book/1220562");

如果有查询参数,可以直接拼接到url里面。如果嫌拼接麻烦,可以通过工具类URIBuilder实现:

//创建一个get请求
            URI uri = null;
            try{
                uri = new URIBuilder()
                        .setScheme("https")
                        .setHost("api.douban.com")
                        .setPath("/v2/movie/in_theaters")
                        .setParameter("city", "北京")
                        .build();
            }catch(URISyntaxException e){
                System.out.println("uri语法错误");
            }
            HttpGet httpget = new HttpGet(uri);

这样请求的地址最后就会变成:https://api.douban.com/v2/movie/in_theaters?city=北京。

post请求

post提交数据一般有两种,表单提交和payload提交方式,写法稍微有点不同。

表单提交
 //2-发送表单数据
            HttpPost request2 = new HttpPost(url);
            List<NameValuePair> formparams = new ArrayList<NameValuePair>();
            formparams.add(new BasicNameValuePair("name", "gameloft9"));//添加参数
            formparams.add(new BasicNameValuePair("pwd", "123456"));
            UrlEncodedFormEntity entity = new UrlEncodedFormEntity(formparams, "UTF-8");
            request2.setEntity(entity);

            //发送请求并获取返回结果
            response = httpclient.execute(request2);
payload提交
  // 1-发送json数据
            HttpPost request = new HttpPost(url);
            String json = "{\n" +
                    "  \"name\":\"gameloft9\",\n" +
                    "  \"pwd\":\"123456\"\n" +
                    "}";
            StringEntity stringEntity = new StringEntity(json, "UTF-8");
            stringEntity.setContentType("application/json");
            request.setEntity(stringEntity);

            //发送请求并获取返回结果
            response = httpclient.execute(request);
返回处理

调用httpclient.execute()方法后,会阻塞直到返回结果或者超时异常,我们通过CloseableHttpResponse对象接受返回结果。从response里面我们可以拿到很多东西,比如状态码,header和我们最关心的body内容。

response.getStatusLine().getStatusCode(); //获取状态码
 response.getHeaders();//获取头
 HttpEntity httpEntity = response.getEntity(); //获取返回内容

我们可以通过下面两个方法读取内容:

InputStream getContent() throws IOException, UnsupportedOperationException;

    void writeTo(OutputStream var1) throws IOException;

如果返回的是string类型的数据,官方很贴心给了一个EntityUtils工具类,通过下面的方法可以直接读取出内容。

String result = EntityUtils.toString(httpEntity, "UTF-8");// 转成string

一般的json报文都可以通过这种方式进行处理。

返回的httpEntity只能读取一次,如果想多次使用,需要用BufferedHttpEntity进行包装:

 HttpEntity httpEntity = response.getEntity(); //获取返回body
 httpEntity = new BufferedHttpEntity(httpEntity); //包装一下,以便可以重复读取

处理完成后需要关闭流(针对getContent()处理,防止忘记关闭inputstream)

EntityUtils.consume(httpEntity);

最后在finnaly里面需要释放资源和客户端,

 try{
                if(response != null){
                    response.close(); //关闭
                }
            }catch(Exception e){}
            try{
                if(httpclient != null){
                    httpclient.close();//关闭客户端
                }
            }catch(Exception e){}
以上就是httpclient的基本用法,后续会更深入的讲解其他方面的内容。
<think>我们正在讨论的是两个不同的Apache HttpClient库版本:httpclient(传统4.x系列)和httpclient5(5.x系列)。这两者属于同一项目但代表不同代际的产品。 根据用户提供的引用和问题: - 引用[1][2][3]提到的是传统4.x版本在Android环境中遇到的问题(冲突、版本声明缺失等),但用户当前问题聚焦于httpclient4与httpclient5的区别 ### 核心区别解析 #### 1. **版本代际与包结构** - **`org.apache.httpcomponents:httpclient`** 代表**HttpComponents HttpClient 4.x系列**(最新4.5.13),采用包名`org.apache.http`[^4]。 ```xml <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>4.5.13</version> </dependency> ``` - **`org.apache.httpcomponents.client5:httpclient5`** 代表**HttpComponents HttpClient 5.x系列**(如5.2.1),包名升级为`org.apache.hc.client5.http`[^5]。 ```xml <dependency> <groupId>org.apache.httpcomponents.client5</groupId> <artifactId>httpclient5</artifactId> <version>5.2.1</version> </dependency> ``` **关键变化**:包路径重构(`org.apache.http` → `org.apache.hc.client5.http`),避免与旧版共存冲突。 #### 2. **API设计改进** - **4.x痛点** - 同步IO模型主导,异步支持弱(需额外依赖`HttpAsyncClient`) - 连接管理繁琐(需手动处理`HttpClientConnectionManager`) - **5.x优化** - 统一同步/异步API(通过`HttpClients.custom().build()`自动选择) - 连接池自动化(默认启用高效连接池) - 引入链式调用(Fluent API)简化请求构建: ```java try (CloseableHttpClient client = HttpClients.createDefault()) { HttpGet request = new HttpGet("https://example.org"); // 5.x特有:链式设置Header request.setHeader("Accept", "application/json"); try (CloseableHttpResponse response = client.execute(request)) { HttpEntity entity = response.getEntity(); // 处理响应 } } ``` #### 3. **协议与标准支持** | **特性** | 4.x | 5.x | |------------------------|------------------------------|------------------------------| | **HTTP/2** | 不支持 | 完整支持(需JDK9+或ALPN库) | | **TLS 1.3** | 需手动配置 | 默认启用 | | **RFC 723x 合规性** | 部分支持 | 全面增强 | #### 4. **性能优化** 5.x系列在以下方面显著提升: - **连接复用率**:通过智能连接保持策略减少TCP握手开销 - **内存管理**:使用`ByteBuffer`替代`byte[]`降低堆压力 - **请求流水线**:支持HTTP/2多路复用,提升并发吞吐量 #### 5. **Android兼容性** 根据引用[1][3]: - **4.x问题**:Android系统内置旧版HttpClient(API 22及以下),导致依赖冲突 **解决方案**: ```gradle android { useLibrary 'org.apache.http.legacy' // 显式声明兼容 } ``` - **5.x优势**: 全新包名彻底规避冲突,但需注意: - 最低API Level要求升至24(Android 7.0+) - 若需支持旧设备,仍建议使用4.x + 兼容配置 --- ### 迁移建议 1. **新项目**:优先选用5.x,享受现代HTTP特性 2. **旧系统升级**: - 重命名所有包导入(`org.apache.http` → `org.apache.hc.client5.http`) - 适配API变更(如`HttpResponse` → `ClassicHttpResponse`) - 使用[官方迁移指南](https://hc.apache.org/httpcomponents-client-5.2.x/migration-guide/) --- §§相关问题§§ 1. HttpClient 5.x如何配置HTTP/2? 2. 如何在Android项目中同时使用HttpClient 4.x和5.x? 3. HttpClient与OkHttp的性能对比如何? </think>### `org.apache.httpcomponents.client5:httpclient5` 与 `org.apache.httpcomponents:httpclient` 的区别详解 #### 1. **核心代际差异** - **`org.apache.httpcomponents:httpclient`** HttpClient **4.x 系列**(最新为 4.5.13),是经典的同步阻塞式 HTTP 客户端库,广泛用于 Java 应用[^1][^2]。 ```xml <!-- Maven 依赖 --> <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>4.5.13</version> </dependency> ``` - **`org.apache.httpcomponents.client5:httpclient5`** HttpClient **5.x 系列**(如 5.2.1),是新一代异步非阻塞实现,支持 HTTP/2 和现代协议[^3]: ```xml <dependency> <groupId>org.apache.httpcomponents.client5</groupId> <artifactId>httpclient5</artifactId> <version>5.2.1</version> </dependency> ``` --- #### 2. **技术架构对比** | **特性** | `httpclient` (4.x) | `httpclient5` (5.x) | |------------------------|----------------------------------------|-----------------------------------------| | **IO 模型** | 同步阻塞(`BasicHttpClient`) | 异步非阻塞(`CloseableHttpAsyncClient`)| | **HTTP/2 支持** | ❌ 不支持 | ✅ 完整支持 | | **包名结构** | `org.apache.http.*` | `org.apache.hc.client5.http.*` | | **内存管理** | 基于 `byte[]` | 基于 `ByteBuffer`(零拷贝优化) | | **连接复用机制** | 手动管理连接池 | 自动智能连接复用 | --- #### 3. **API 设计差异** - **4.x 经典同步调用**: ```java CloseableHttpClient client = HttpClients.createDefault(); HttpGet request = new HttpGet("https://example.com"); CloseableHttpResponse response = client.execute(request); // 阻塞调用 ``` - **5.x 异步非阻塞**: ```java CloseableHttpAsyncClient client = HttpAsyncClients.createDefault(); client.start(); SimpleHttpRequest request = SimpleHttpRequests.get("https://example.com"); Future<SimpleHttpResponse> future = client.execute(request, null); // 非阻塞 SimpleHttpResponse response = future.get(); // 异步获取结果 ``` --- #### 4. **Android 兼容性问题** 根据引用[1][3]: - **4.x 在 Android 中的冲突**: Android SDK 内置旧版 `org.apache.http` 包,导致依赖冲突。需在 `build.gradle` 添加: ```gradle android { useLibrary 'org.apache.http.legacy' // 显式声明兼容 } ``` - **5.x 的优势**: 全新包名 `org.apache.hc.client5` 彻底规避冲突,但需最低 **API Level 24**(Android 7.0+)[^3]。 --- #### 5. **性能与适用场景** - **4.x 适用场景**: - 传统同步业务逻辑 - Android 低版本兼容(API < 24) - 简单 HTTP 请求(无 HTTP/2 需求) - **5.x 优势场景**: - 高并发微服务(异步 IO 提升吞吐量) - HTTP/2 协议应用(如 gRPC 网关) - 现代云原生架构(配合 Reactive 编程) --- ### 迁移建议 1. **新项目**:优先选择 `httpclient5`,利用其异步和 HTTP/2 特性 2. **旧系统升级**: - 替换包路径:`org.apache.http` → `org.apache.hc.client5.http` - 重构阻塞调用为异步模式 - 验证 HTTP/2 功能依赖(需 JDK 9+ 或 ALPN 库) ---
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值