掌握HttpClient技术:从基础到实战(Apache)

article/2025/7/14 4:29:18

目录

前言

一、Apache HttpClient简介

二、HttpClient基础使用

1. 添加依赖

2. 创建HttpClient实例

3. 发送GET请求

4. 发送POST请求

三、HttpClient高级配置与实战案例

1. 连接池优化

2. 超时与重试配置

3. 文件上传(Multipart)

总结


前言

在Java 11之前的版本中,标准库提供的HttpURLConnection功能较为基础,难以满足复杂HTTP场景(如连接池管理、异步请求、灵活重试等)的需求。Apache HttpClient(属于Apache HttpComponents项目)作为Java生态中最成熟、功能最全面的HTTP客户端库之一,长期被广泛应用于企业级开发。本文将从设计、基础用法到实战案例,系统讲解Apache HttpClient的技术细节。


一、Apache HttpClient简介

Apache HttpClient是由Apache软件基金会维护的一款开源HTTP客户端库,它全面支持HTTP/1.1协议,并为用户提供了一系列强大的核心能力,使其成为开发高效、可靠网络应用的理想选择,其提供以下核心能力:

  • 连接池管理:Apache HttpClient内置了高效的连接池管理机制,能够复用TCP连接,从而显著减少连接建立和断开的握手开销。通过连接池,客户端能够在多个请求之间共享连接,这不仅提升了性能,还降低了资源消耗。
  • 灵活的请求配置:该库提供了丰富的配置选项,支持设置请求超时、配置代理服务器、管理重定向策略、处理Cookie以及实现身份认证等,这些配置选项使得HttpClient能够灵活应对各种复杂的网络环境和请求需求。
  • 扩展性:Apache HttpClient通过拦截器(Interceptor)机制,允许用户自定义日志记录、请求重试、响应缓存等逻辑,拦截器机制使得HttpClient具有高度的可扩展性,能够轻松集成到各种复杂的系统中。
  • 同步/异步请求支持:HttpClient不仅兼容传统的阻塞I/O模型,允许用户发起同步请求并等待响应,还提供了异步非阻塞请求的支持(需结合异步HTTP客户端)。异步请求支持使得HttpClient能够处理大量并发请求,同时保持应用的响应性和可扩展性。

用户在选择HttpClient版本时,需要根据项目的具体需求、目标Java版本以及对新特性的需求进行权衡,版本选择如下:

  • HttpClient 4.x:作为广泛使用的稳定版本,HttpClient 4.x已经经过了充分的测试和验证,适用于大多数应用场景。
  • HttpClient 5.x:作为新一代API,HttpClient 5.x在性能和功能上进行了多项改进,并支持HTTP/2协议(需Java 8及以上版本)。

二、HttpClient基础使用

1. 添加依赖

为了在Java项目中使用Apache HttpClient,需要在项目的构建文件中添加相应的依赖,Maven配置如下(以4.5.13版本为例):

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

2. 创建HttpClient实例

创建默认实例:

为了发送HTTP请求,需要创建一个CloseableHttpClient实例,可以通过HttpClients.createDefault()方法直接获取预配置的HttpClient实例,该实例采用以下默认参数:

CloseableHttpClient httpClient = HttpClients.createDefault();

非默认配置的实例

以下案例展示如何通过HttpClientBuilder定制化配置CloseableHttpClient,覆盖连接超时、代理、重试策略、SSL证书校验等关键参数:

import org.apache.http.HttpHost;
import org.apache.http.HttpRequestInterceptor;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.StandardHttpRequestRetryHandler;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.ssl.SSLContextBuilder;
import javax.net.ssl.SSLContext;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.util.UUID;
import java.util.concurrent.TimeUnit;public class ApacheHttpClientExample {public static CloseableHttpClient createCustomHttpClient() throws NoSuchAlgorithmException, KeyStoreException, KeyManagementException {// 连接池配置PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager();connManager.setMaxTotal(200);          // 最大连接数connManager.setDefaultMaxPerRoute(50); // 每个路由(目标主机)的最大并发连接数connManager.closeIdleConnections(60, TimeUnit.SECONDS); // 关闭空闲超时连接// 超时配置RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(5000)    // 连接建立超时(5秒).setSocketTimeout(15000)    // 数据传输超时(15秒).setConnectionRequestTimeout(3000) // 从连接池获取连接的超时(3秒).build();// SSL配置(信任自签名证书)SSLContext sslContext = SSLContextBuilder.create().loadTrustMaterial(new TrustSelfSignedStrategy()).build();SSLConnectionSocketFactory sslSocketFactory = new SSLConnectionSocketFactory(sslContext,new String[]{"TLSv1.2", "TLSv1.3"}, // 支持的协议版本null,SSLConnectionSocketFactory.getDefaultHostnameVerifier());// 重试策略StandardHttpRequestRetryHandler retryHandler = new StandardHttpRequestRetryHandler(3,      // 最大重试次数true    // 对非幂等请求(如POST)也重试(需业务确保安全性));// 构建HttpClientreturn HttpClientBuilder.create().setConnectionManager(connManager)          // 连接池.setDefaultRequestConfig(requestConfig)     // 超时配置.setSSLSocketFactory(sslSocketFactory)      // SSL配置.setRetryHandler(retryHandler)              // 重试策略.setProxy(new HttpHost("proxy.example.com", 8080)) // 代理服务器.disableCookieManagement()                  // 禁用Cookie管理(按需启用).setUserAgent("Custom-Client/1.0")          // 自定义User-Agent.addInterceptorFirst((HttpRequestInterceptor) (request, context) ->request.addHeader("X-Request-ID", UUID.randomUUID().toString())) // 自定义请求头.build();}public static void main(String[] args) {try {CloseableHttpClient httpClient = createCustomHttpClient();// 使用httpClient进行HTTP请求// ...} catch (Exception e) {e.printStackTrace();}}
}

3. 发送GET请求

发送GET请求是HttpClient最常见的用法之一,以下是一个使用Apache HttpClient库发送HTTP GET请求的案例:

import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;public class ApacheHttpClientExample {public static void main(String[] args) {try (CloseableHttpClient httpClient = HttpClients.createDefault()) {HttpGet request = new HttpGet("https://jsonplaceholder.typicode.com/posts/1");try (CloseableHttpResponse response = httpClient.execute(request)) {System.out.println("Status Code: " + response.getStatusLine().getStatusCode());String responseBody = EntityUtils.toString(response.getEntity());System.out.println("Response Body: " + responseBody);}} catch (Exception e) {e.printStackTrace();}}
}

该案例在main方法中,使用try-with-resources语句创建了CloseableHttpClient实例,该实例负责发送HTTP请求,并创建了一个HttpGet请求对象,目标URL指向https://jsonplaceholder.typicode.com/posts/1(提供假数据的API)。然后再次使用try-with-resources语句执行该请求并获取CloseableHttpResponse响应对象。在响应对象的作用域内,程序打印了HTTP响应的状态码,并使用EntityUtils.toString方法将响应实体转换为字符串,最后打印出响应体的内容。如果在执行请求或处理响应时发生任何异常,这些异常将被捕获并打印到标准错误输出。

https://jsonplaceholder.typicode.com/posts/1的内容如下:

运行结果:

4. 发送POST请求

发送POST请求与GET请求类似,只是需要在请求体中包含要发送的数据,通常POST请求用于提交表单数据或JSON数据。以下案例展示了如何使用Apache HttpClient库在Java中发送一个包含JSON请求体的HTTP POST请求,并处理响应。

import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;public class ApacheHttpClientExample {public static void main(String[] args) {try (CloseableHttpClient httpClient = HttpClients.createDefault()) {HttpPost request = new HttpPost("https://jsonplaceholder.typicode.com/posts");// 设置JSON请求体String json = "{\"title\":\"foo\",\"body\":\"bar\",\"userId\":1}";request.setEntity(new StringEntity(json, ContentType.APPLICATION_JSON));// 添加自定义请求头request.addHeader("X-Custom-Header", "value");try (CloseableHttpResponse response = httpClient.execute(request)) {System.out.println("Status Code: " + response.getStatusLine().getStatusCode());String responseBody = EntityUtils.toString(response.getEntity());System.out.println("Response Body: " + responseBody);}} catch (Exception e) {e.printStackTrace();}}
}

在方法中,利用try-with-resources语句创建了CloseableHttpClient实例以确保资源正确关闭。之后创建HttpPost请求对象并指向目标URL,设置了JSON格式的请求体内容类型,并附加了自定义请求头,通过执行请求并捕获响应,程序打印了HTTP响应的状态码和响应体内容。

运行结果:

Status Code: 201
Response Body: {"title":"foo","body":"bar","userId":1,"id":101}

三、HttpClient高级配置与实战案例

1. 连接池优化

在高性能的HTTP客户端应用中,连接池的管理是至关重要的。Apache HttpClient库提供了一个强大的工具PoolingHttpClientConnectionManager,它允许开发者高效地管理和复用HTTP连接,从而显著提升应用的性能和资源利用率。通过PoolingHttpClientConnectionManager管理连接池的案例如下:

import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;public class ApacheHttpClientExample {public static void main(String[] args) {PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager();connManager.setMaxTotal(200);          // 最大连接数connManager.setDefaultMaxPerRoute(20); // 每个路由(目标主机)的最大连接数try (CloseableHttpClient httpClient = HttpClients.custom().setConnectionManager(connManager).build()) {// 执行高并发请求...} catch (Exception e) {e.printStackTrace();}}
}

2. 超时与重试配置

在构建高性能、高可靠性的HTTP客户端应用时,超时与重试配置是两个至关重要的方面,它们不仅影响应用的响应速度,还直接关系到应用的稳定性和用户体验。设置超时与重试配置的案例如下:

import org.apache.http.client.config.RequestConfig;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultHttpRequestRetryHandler;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;public class ApacheHttpClientExample {public static void main(String[] args) {RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(5000)    // 连接超时5秒.setSocketTimeout(10000)    // 数据传输超时10秒.build();// 自定义重试策略(默认重试3次)HttpClientBuilder builder = HttpClients.custom().setDefaultRequestConfig(requestConfig).setRetryHandler(new DefaultHttpRequestRetryHandler(3, true));try (CloseableHttpClient httpClient = builder.build()) {// 执行请求...} catch (Exception e) {e.printStackTrace();}}
}

3. 文件上传(Multipart)

为了在Java项目中使用Apache HttpClient进行文件上传,需要在项目的构建文件中添加相应的依赖,Maven配置如下(以4.5.13版本为例):

<dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpmime</artifactId><version>4.5.13</version>
</dependency>

以下是一个使用了Apache HttpClient来发送包含文件上传HTTP POST请求的案例:

import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;import java.io.File;public class ApacheHttpClientExample {public static void main(String[] args) {try (CloseableHttpClient httpClient = HttpClients.createDefault()) {HttpPost request = new HttpPost("https://example.com/upload");// 构建Multipart请求体MultipartEntityBuilder builder = MultipartEntityBuilder.create();builder.addPart("file", new FileBody(new File("test.txt")));builder.addTextBody("comment", "Sample File");request.setEntity(builder.build());try (CloseableHttpResponse response = httpClient.execute(request)) {// 处理响应...}} catch (Exception e) {e.printStackTrace();}}
}

总结

Apache HttpClient在Java 11之前的版本中是处理复杂HTTP通信的首选方案。通过灵活的配置、高效的连接池管理和丰富的扩展能力,它能够满足企业级应用的高性能需求。然而,随着Java 11+标准库HttpClient的普及,新项目建议优先使用原生方案,而旧系统仍可依赖Apache HttpClient的稳定性和成熟生态。


http://www.hkcw.cn/article/jhyVndYjqR.shtml

相关文章

EXCEL--累加,获取大于某个值的第一个数

一、函数 LET(data,A1:A5,cumSum,SCAN(0,data,LAMBDA(a,b,ab)),idx,MATCH(TRUE,cumSum>C1,0),INDEX(data,idx)) 二、函数拆解 1、LET函数&#xff1a;LET(name1, value1, [name2, value2, ...], calculation) name1, name2...&#xff1a;自定义的变量名&#xff08;需以字…

D. Gellyfish and Camellia Japonica【Codeforces Round 1028 (Div. 2)】

D. Gellyfish and Camellia Japonica 思路 贪心构造&#xff08;其实是思维题&#xff09; 先找必要性&#xff0c;再验证充分性&#xff1a; 倒着求出每个位置的下界作为这个位置的值&#xff0c;再正着验证构造出的这个数列是否合法。 代码非常短&#xff0c;这个题如果当时…

GODOT引擎学习日志

最近在学习使用GODOT引擎&#xff0c;发现这个东西很好很强大。此为背景。 刚开始学习&#xff0c;在使用camera3D的时候&#xff0c;发现使用鼠标滚轮进行视角缩放的时候&#xff0c;网上有些内容不全&#xff0c;于是找了一下。其实很简单&#xff1a; Camera3D有个属性是siz…

普通二叉树 —— 最近公共祖先问题解析(Leetcode 236)

&#x1f3e0;个人主页&#xff1a;尘觉主页 文章目录 普通二叉树 —— 最近公共祖先问题解析&#xff08;Leetcode 236&#xff09;&#x1f9e0; 问题理解普通二叉树与 BST 的区别&#xff1a; &#x1f4a1; 解题思路关键思想&#xff1a;&#x1f4cc; 举个例子&#xff1a…

Dify 部署问题处理

Dify介绍 Dify 是一款开源的大语言模型(LLM) 应用开发平台。它融合了后端即服务&#xff08;Backend as Service&#xff09;和 LLMOps 的理念&#xff0c;使开发者可以快速搭建生产级的生成式 AI 应用。即使你是非技术人员&#xff0c;也能参与到 AI 应用的定义和数据运营过程…

《操作系统真相还原》——中断

可以毫不夸张的说&#xff0c;操作系统离不开中断 此时我们将中断处理程序放在了汇编文件中了&#xff0c;很显然我们不能很方便的编写中断处理程序&#xff0c;不如在汇编程序里调用c函数。 在这个感觉过可以在c语言中直接内联汇编完成这些。 定时器 将时钟中断的频率提高后…

腾讯位置商业授权沿途搜索服务开发指南

概述 通过本服务检索某段道路附近的POI信息&#xff0c;可配合路线规划&#xff0c;为用户提供沿途服务区、加油站等搜索功能。 注&#xff1a; 1、本服务属于高级付费服务&#xff0c;如需试用请提交商务合作开通服务试用。 2、本接口有大小限制&#xff0c;接口长度不能超…

内容中台的实施基石是什么?

标准化流程体系构建 在企业内容中台建设中&#xff0c;标准化流程体系是确保内容生产、管理和分发效率的核心框架。通过定义元数据规范、内容分类规则及跨部门协作机制&#xff0c;能够实现从内容创建到归档的全链路标准化运作。例如&#xff0c;Baklib作为支持团队协作与权限…

信息安全管理与评估2024山东卷WAF答案

需要其他赛题解析的可联系博主

[免费]微信小程序网上花店系统(SpringBoot后端+Vue管理端)【论文+源码+SQL脚本】

大家好&#xff0c;我是java1234_小锋老师&#xff0c;看到一个不错的微信小程序网上花店系统(SpringBoot后端Vue管理端)【论文源码SQL脚本】&#xff0c;分享下哈。 项目视频演示 【免费】微信小程序网上花店系统(SpringBoot后端Vue管理端) Java毕业设计_哔哩哔哩_bilibili 项…

定制开发开源AI智能名片驱动下的海报工厂S2B2C商城小程序运营策略——基于社群口碑传播与子市场细分的实证研究

摘要 本文聚焦“定制开发开源AI智能名片S2B2C商城小程序”技术与海报工厂业务的融合实践&#xff0c;探讨其如何通过风格化海报矩阵的精细化开发、AI技术驱动的用户体验升级&#xff0c;以及S2B2C模式下的社群裂变机制&#xff0c;实现“工具功能-社交传播-商业变现”的生态…

制作个人Github学术主页

1.fork一个模板 从模板网站Jekyll Themes fork一个模板&#xff0c;并在repository name里填入yourname.github.io 2.生成自己的site 按顺序点击以下按钮&#xff0c;修改Branch为master /root 然后点击save &#xff0c;等待一会后刷新&#xff0c;便会生成一个新的site。 3.…

无法访问公网或 DNS 解析失败怎么办?

当云服务器无法访问公网或DNS 解析失败时&#xff0c;可能会导致无法 ping 外网、不能下载软件或无法访问网站。下面是详细的排查和解决方法&#xff1a; 莱卡云 &#x1f9ed; 一、问题现象说明 问题表现无法访问公网ping 8.8.8.8 不通DNS 解析失败ping www.baidu.com 报错“…

简道云--第一个表单

一、创建表单 新建应用--创建空白应用--名称--新建表单--创建空白表单 二、表单内容 三、表单发布及数据收集 表单公共发布案例&#xff1a;员工基础信息表

web架构2------(nginx多站点配置,include配置文件,日志,basic认证,ssl认证)

一.前言 前面我们介绍了一下nginx的安装和基础配置&#xff0c;今天继续来深入讲解一下nginx的其他配置 二.nginx多站点配置 一个nginx上可以运行多个网站。有多种方式&#xff1a; http:// ip/域名 端口 URI 其中&#xff0c;ip/域名变了&#xff0c;那么网站入口就变了…

深度学习|pytorch基本运算-hadamard积、点积和矩阵乘法

【1】引言 pytorch对张量的基本运算和线性代数课堂的教学有一些区别&#xff0c;至少存在hadamard积、点积和矩阵乘法三种截然不同的计算方法。 【2】hadamard积 hadamard积是元素对位相乘&#xff0c;用“*”连接张量&#xff0c;代码&#xff1a; # 导入包 import torch …

uniapp路由跳转toolbar页面

需要阅读uview-ui的API文档 注意需要使用type参数设置后才起作用 另外route跳转的页面会覆盖toolbar工具栏 toConternt(aid) {console.log(aid:, aid)this.$u.route({// url: "pages/yzpg/detail",url: "pages/yzappl/index",// url: "pages/ind…

数据结构哈希表总结

349. 两个数组的交集 力扣题目链接(opens new window) 题意&#xff1a;给定两个数组&#xff0c;编写一个函数来计算它们的交集。 说明&#xff1a; 输出结果中的每个元素一定是唯一的。 我们可以不考虑输出结果的顺序。 public int[] intersection(int[] nums1, int[] num…

【深度学习新浪潮】多模态模型如何处理任意分辨率输入?

多模态模型处理任意分辨率输入的能力主要依赖于架构设计的灵活性和预处理技术的结合。以下是核心方法及技术细节: 一、图像模态的分辨率处理 1. 基于Transformer的可变补丁划分(ViT架构) 补丁化(Patch Embedding): 将图像分割为固定大小的补丁(如1616或3232像素),不…

CSS之动画(奔跑的熊、两面反转盒子、3D导航栏、旋转木马)

一、 2D转换 1.1 transform: translate( ) 转换&#xff08;transform&#xff09; 是CSS3中具有颠覆性的特征之一&#xff0c;可以实现元素的位移、旋转、缩放等效果 移动&#xff1a;translate 旋转&#xff1a;rotate 缩放&#xff1a;scale 下图为2D转换的坐标系 回忆…