← [ BACK_TO_NOTES ]

Java HttpClient

JDK HttpClient 发送 HTTP 请求:同步/异步、超时与响应体处理基础。

#concept #growing #dev #java

[!info] related notes

Java HttpClient

这个概念为什么出现

服务常调用下游 HTTP API。JDK 11+ java.net.http.HttpClient 提供现代客户端,减少对第三方的基础依赖。

[!abstract] 一句话理解 HttpClient + HttpRequest + HttpResponse 发送 HTTP;应设置超时、处理非 2xx,并避免在错误线程模型上阻塞。

最小可运行示例

场景:调用本机健康检查(JDK 21 示例,需服务已启动)

import java.net.URI;
import java.net.http.*;
import java.time.Duration;

public class HealthClient {
    public static void main(String[] args) throws Exception {
        URI endpoint = URI.create(args.length == 0 ? "http://localhost:8080/health" : args[0]);
        HttpRequest req = HttpRequest.newBuilder(endpoint)
                .timeout(Duration.ofSeconds(3))
                .GET()
                .build();
        try (HttpClient client = HttpClient.newBuilder()
                .connectTimeout(Duration.ofSeconds(2))
                .build()) {
            HttpResponse<Void> resp = client.send(req, HttpResponse.BodyHandlers.discarding());
            if (resp.statusCode() < 200 || resp.statusCode() >= 300) {
                throw new IllegalStateException("health status=" + resp.statusCode());
            }
            System.out.println(resp.statusCode());
        }
    }
}
javac HealthClient.java && java HealthClient

先启动 HTTP 服务示例,再运行客户端,成功时输出 200;可通过第一个命令行参数指定其他健康检查 URL。连接失败、超时、中断或非 2xx 均使本例以异常退出,不把失败伪装成成功。

HttpClient 自 Java 11 提供;本例使用 Java 21 新增的 AutoCloseable 生命周期支持。长期服务通常复用客户端连接池,在服务停机时关闭,而不是每次请求新建。

结合场景再看三个关注点

  1. 超时必设。
  2. HTTP 4xx/5xx 本身不会让 send 自动抛异常,BodyHandler 也不会自动将其视为失败;需按契约检查状态。
  3. 异步 sendAsync 返回 CF。

核心概念与准确模型

1. 请求与构建器

构建出的 HttpRequest 不可变;Builder 可变,不能把 builder 当作线程安全的不可变请求共享。

2. BodyHandlers/BodyPublishers

BodyPublisher 提供请求体,BodyHandler 决定响应体如何消费。ofString/ofByteArray 聚合完整响应体;大响应可用流式处理,但 ofInputStream 返回的流必须读完或关闭。discarding 忽略内容但仍消费响应体。

3. 重定向与 HTTP 版本

默认重定向策略是 NEVER;客户端默认偏好 HTTP/2,协商结果仍可能是 HTTP/1.1,应看 response.version()。

边界情况与反直觉行为

  1. 代理与 TLS 信任库。
  2. 大下载要流式 handler。
  3. send 可抛 InterruptedException;若捕获后不再向上传递,应恢复中断标志。取消 sendAsync 返回的 Future 是尽力中止操作,不保证服务端尚未执行请求。

常见误区

[!warning] 常见误区:忽略状态码只读 body 错误页 HTML 会被当成功解析。

工程实践

  1. 统一客户端配置(超时、指标)。
  2. 重试需结合故障类型、幂等性、请求体能否重放与剩余时间预算;超时不证明服务端没有完成操作。
  3. 传播 correlation id 头。
  4. 契约测试下游。

本节总结

  • JDK 现代 HTTP 客户端
  • 超时+状态码
  • 同步/异步可选

自测题

  1. connectTimeout 与 request timeout 差别直觉?
  2. 何时用 sendAsync?
参考答案
  1. connectTimeout 只约束新连接建立,复用连接时不生效;请求 timeout 约束等待响应。流式 handler 可能在响应体读完前返回,不能将其当作后续流读取的逐次空闲超时,完整消费仍需应用级期限。
  2. 需要非阻塞组合多个下游调用时。

延伸阅读与资料来源

资料类型支撑内容
HttpClient APIAPI客户端
创建于 2026/7/15 更新于 2026/10/6
Digital Biome
Access

键盘导航

j / k / ↑ / ↓
选择对象
Enter / o
打开选择
/ 或 Ctrl+K
全站搜索
i / f / 1–4
筛选当前列表
g → h / l / p / t / a
首页 / 笔记 / 项目 / 工具 / About
r → 1–9
打开所选对象的关联
u
返回上一页
Esc
关闭浮层 / 取消命令;输入框内清空文本