探索 Java 中的新 HTTP 客户端
(java.net.http.HttpClient,从 Java 11 开始的标准 HTTP 客户端)
从 Java 11 开始,JDK 正式引入了现代化的 HttpClient(java.net.http 包),它取代了老旧的 HttpURLConnection,并成为推荐的内置 HTTP 客户端。
这个客户端支持 HTTP/1.1、HTTP/2(甚至未来 JDK 26+ 支持 HTTP/3),同时提供同步和异步两种调用方式,API 设计简洁、现代、功能强大,且零依赖。
下面从零基础到生产级用法,一次性讲透。
一、为什么用新的 HttpClient?(对比老方式)
| 特性 | HttpURLConnection (老古董) | Apache HttpClient / OkHttp | 新 HttpClient (Java 11+) |
|---|---|---|---|
| 引入版本 | JDK 1.1 | 第三方依赖 | JDK 11(9/10 孵化) |
| 依赖 | 无 | 需要引入 jar | 无(JDK 自带) |
| HTTP/2 支持 | 不支持 | 支持(部分版本) | 原生支持 |
| 异步支持 | 几乎无 | 支持(回调/Future) | 原生 CompletableFuture |
| API 现代程度 | 非常老旧 | 较好 | Builder 风格、流式 |
| WebSocket | 不支持 | OkHttp 支持 | 支持 |
| 性能 | 一般 | 优秀 | 优秀(尤其是 HTTP/2) |
| 推荐场景 | 遗留系统 | 需要极致配置/兼容性 | 新项目首选 |
结论:
- Java 11+ 新项目 → 优先用 java.net.http.HttpClient
- 需要极致自定义或 Java 8 → 考虑 OkHttp / Apache HttpClient 5
- Spring Boot 3+ → 可以用 RestClient(底层基于 HttpClient)
二、快速上手(最常用写法)
1. 同步 GET 请求(最简单)
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.http.HttpResponse.BodyHandlers;
public class SimpleGet {
public static void main(String[] args) throws Exception {
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.github.com"))
.header("Accept", "application/json")
.GET()
.build();
HttpResponse<String> response = client.send(request, BodyHandlers.ofString());
System.out.println("状态码: " + response.statusCode());
System.out.println("Body: " + response.body());
}
}
2. 异步 GET(推荐高并发场景)
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.example.com/data"))
.build();
client.sendAsync(request, BodyHandlers.ofString())
.thenApply(HttpResponse::body)
.thenAccept(System.out::println)
.join(); // 等待完成(生产中通常不 join)
3. POST JSON(常见场景)
String json = """
{
"name": "张三",
"age": 28
}
""";
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.example.com/users"))
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(json))
.build();
4. 表单 POST(x-www-form-urlencoded)
String form = "username=admin&password=123456";
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://example.com/login"))
.header("Content-Type", "application/x-www-form-urlencoded")
.POST(HttpRequest.BodyPublishers.ofString(form))
.build();
5. 上传文件(Multipart)
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://example.com/upload"))
.header("Content-Type", "multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW")
.POST(HttpRequest.BodyPublishers.ofFile(Path.of("photo.jpg")))
.build();
(复杂 multipart 推荐用第三方库辅助构建 body,或自己拼接)
三、创建 HttpClient 的最佳实践(生产级配置)
HttpClient client = HttpClient.newBuilder()
.version(HttpClient.Version.HTTP_2) // 优先 HTTP/2
//.version(HttpClient.Version.HTTP_1_1) // 强制 HTTP/1.1
.followRedirects(HttpClient.Redirect.NORMAL) // 自动重定向(除 https→http)
.connectTimeout(Duration.ofSeconds(10))
.sslContext(SSLContext.getDefault()) // 自定义 SSL
//.executor(Executors.newFixedThreadPool(16)) // 自定义线程池(异步用)
.build();
推荐:不要每次请求都 new HttpClient,而是复用一个实例(内部有连接池,支持 HTTP/2 多路复用)。
四、常见高级用法
- 流式响应(处理大文件下载)
HttpResponse<Stream<String>> response = client.send(
request,
HttpResponse.BodyHandlers.ofLines()
);
- WebSocket 支持
HttpClient client = HttpClient.newHttpClient();
WebSocket ws = client.newWebSocketBuilder()
.buildAsync(URI.create("wss://echo.websocket.org"), new WebSocket.Listener() {
// onOpen, onText, onClose 等回调
})
.join();
- 认证(Basic / Bearer)
HttpRequest request = HttpRequest.newBuilder()
.uri(...)
.header("Authorization", "Bearer " + token)
.build();
五、常见问题 & 最佳实践(2024-2025)
- 连接池:HttpClient 内部自动管理,不要频繁创建实例
- 异常处理:send() 抛出 IOException / InterruptedException,sendAsync 用 exceptionally()
- 超时:connectTimeout + request timeout(通过 Duration)
- HTTP/3:JDK 26+ 支持(目前实验阶段)
- 与 Spring 集成:Spring Boot 3+ 的 RestClient / WebClient 底层可基于 HttpClient
- 性能:HTTP/2 下复用连接 + 多路复用,性能接近甚至优于很多第三方库
六、总结一句话
Java 11+ 的 HttpClient 是现代 Java 网络编程的首选:零依赖、支持 HTTP/2、同步/异步一体的流式 API、WebSocket 支持、简洁强大。
推荐口诀:
- 小项目 / 快速原型 → 直接 newHttpClient()
- 中大型项目 → 复用一个配置好的 HttpClient 实例
- 高并发 → 优先异步 + CompletableFuture 链式调用
- 需要极致功能(如自动重试、连接池精细控制)→ 再考虑 OkHttp / Apache HttpClient 5
想看具体场景的完整示例吗?(如 OAuth2 认证、文件上传、SSE、结合虚拟线程等)欢迎继续问~