Apache HttpClient 4.5.x 学习总结三:HTTPEntity
重点概括
实体不是数据本身,而是数据+元数据的封装器这个本质。
比如:信封(元数据)里面装着实际货物(数据)
一、专业术语解读
1. 定义
HttpEntity 是 Apache HttpClient 中的核心接口,代表可携带内容的 HTTP 消息实体(如请求体或响应体)。它封装了:
- 内容数据(二进制流或字符文本)
- 元数据(Content-Type、Content-Length、Content-Encoding 等头部信息)
- 访问方法(获取输入流、写入输出流)
2. 关键特性
| 特性 | 说明 |
|---|---|
| 可重复性 | 仅 自包含实体(如 ByteArrayEntity)支持多次读取内容;流式实体(如网络响应)通常只能读取一次。 |
| 传输编码 | 支持分块传输(setChunked(true)),适用于大文件流式上传。 |
| 资源管理 | 必须通过 getContent().close() 或 EntityUtils.consume() 释放底层资源(如 Socket 连接)。 |
3. 实体类型
classDiagram
class HttpEntity {
+getContent() InputStream
+getContentType() Header
+getContentLength() long
+isRepeatable() boolean
}
HttpEntity <|-- AbstractHttpEntity
AbstractHttpEntity <|-- ByteArrayEntity
AbstractHttpEntity <|-- StringEntity
AbstractHttpEntity <|-- FileEntity
AbstractHttpEntity <|-- InputStreamEntity
note for InputStreamEntity "不可重复读取"
note for ByteArrayEntity "内存中,可重复读取"
二、通俗易懂解读
1. 现实类比
将 HttpEntity 想象成一个快递包裹:
- 包裹内容(
Content):你要寄送的文件或商品(相当于 HTTP 的消息体)。 - 快递单(
Metadata):寄件人/收件人信息、重量、包装类型(相当于 Content-Type 等头部)。 - 运输规则(
Rules):易碎品只能小心搬运一次(不可重复实体),普通物品可多次开箱检查(可重复实体)。
2. 操作场景
| 操作 | 类比 |
|---|---|
| 发送请求(上传) | 将本地文件(FileEntity)或字符串(StringEntity)打包成包裹,交给快递员(HttpClient)发送。 |
| 接收响应(下载) | 拆开服务器返回的包裹: - 小件直接取出( EntityUtils.toString())- 大件需流式拆箱( entity.getContent())。 |
| 资源回收 | 拆完包裹后必须处理纸箱(调用 close()),否则仓库(服务器连接)会被占满。 |
3. 为什么需要区分实体类型?
-
流式实体(如
InputStreamEntity)
→ 像直播视频流:数据从网络实时传输,只能看一次,无法回放。
→ 适用场景:上传大型文件(避免内存溢出)。 -
自包含实体(如
ByteArrayEntity)
→ 像U盘里的电影:数据已完整缓存在内存,可反复播放。
→ 适用场景:发送小文件或表单数据(可重复读取)。
三、开发中的关键决策点
1. 如何选择实体类型?
| 场景 | 推荐实体类型 | 原因 |
|---|---|---|
| 发送 JSON 字符串 | StringEntity |
内存操作快,可重复提交 |
| 上传 2GB 大文件 | FileEntity |
不占内存,支持流式传输 |
| 接收 API 响应(小 JSON) | BufferedHttpEntity |
缓冲到内存,便于重复解析 |
| 接收 1GB 文件 | 原始流式实体 | 避免内存溢出,流式写入磁盘 |
2. 必须遵守的资源释放规则
// 正确做法:使用 try-with-resources 确保关闭
try (CloseableHttpResponse response = httpClient.execute(request)) {
HttpEntity entity = response.getEntity();
if (entity != null) {
try (InputStream is = entity.getContent()) {
// 处理流...
} // 自动关闭流
}
} // 自动关闭响应
// 错误做法:未关闭流 → 连接泄漏!
InputStream is = response.getEntity().getContent();
String data = IOUtils.toString(is); // 若异常抛出,流未关闭!
四、总结
- 本质:HttpEntity 是 HTTP 消息体的抽象,承载数据 + 元数据,提供统一访问接口。
- 核心矛盾:流式传输(高效处理大数据)vs 可重复性(方便操作)。
- 黄金法则:
根据数据大小和访问需求选择实体类型,并严格关闭资源!
小数据用内存实体(ByteArrayEntity),大数据用流式实体(FileEntity),响应处理优先用ResponseHandler。
理解 HttpEntity 的核心在于把握 数据载体、元信息、资源生命周期 三大角色,类比现实中的物流场景即可轻松映射到代码实践。
浙公网安备 33010602011771号