Java 11 新增的 HTTP Client API(JEP 321)
一、概述
Java 11引入了一个全新的标准HTTP客户端API,位于java.net.http包中,旨在取代自Java早期就存在的HttpURLConnection类。该API此前在Java 9中以孵化器模块形式出现,经过Java 10的迭代更新,最终在Java 11中正式标准化。新的HTTP客户端提供了一种更现代化、更易用的方式来处理HTTP通信,支持HTTP/2和WebSocket,并同时提供同步与异步两种编程模型。
与传统的HttpURLConnection相比,java.net.http.HttpClient具备以下显著优势:
| 特性 | 说明 |
|---|---|
| 无需第三方依赖 | 属于Java标准库的一部分,开箱即用 |
| HTTP/2原生支持 | 支持多路复用、头部压缩等性能优化特性 |
| 异步非阻塞 | 基于CompletableFuture,可高效处理高并发场景 |
| 构建器模式 | 采用流式API,配置和构建过程简洁直观 |
| 内置WebSocket客户端 | 无需额外依赖即可实现WebSocket通信 |
在Java 11之前,开发者通常使用HttpURLConnection(功能过于底层)或引入Apache HttpClient等第三方库(增加依赖管理负担)来处理HTTP请求。新的HTTP Client API弥补了标准库在这一领域的长期空白。
二、核心组件:HttpClient、HttpRequest与HttpResponse
HTTP Client API围绕三个核心类设计,职责划分清晰:
- HttpClient:负责管理客户端层面的配置(如协议版本、重定向策略、代理、认证器等),并实际执行请求的发送。
HttpClient实例一旦创建即不可变,可重复用于发送多个请求。 - HttpRequest:使用构建器模式构建,封装单个HTTP请求的全部信息,包括URI、HTTP方法、请求头、请求体等。
HttpRequest同样是不可变的,可多次发送。 - HttpResponse:封装服务器返回的响应,包含状态码、响应头和响应体。响应体可以通过
BodyHandler以字符串、字节数组、文件等多种方式消费。
这种清晰的三层分离使得HTTP通信的各个关注点得以解耦:客户端管理连接和策略,请求描述具体调用,响应承载返回数据。
三、创建和配置HttpClient
3.1 基本创建方式
HttpClient提供了两种创建实例的方式:
HttpClient.newHttpClient():返回使用默认配置的HttpClient实例,适用于大多数基本场景。HttpClient.newBuilder():返回构建器,允许对客户端进行详细配置。
3.2 常用配置项
以下是一个配置较为完整的HttpClient构建示例:
1 | package com.johnson.example.httpclient; |
主要配置项说明:
| 配置方法 | 作用 |
|---|---|
version(Version) |
设置首选HTTP协议版本。HTTP_2会优先尝试HTTP/2,协商失败则回退至HTTP/1.1 |
followRedirects(Redirect) |
配置重定向策略。Redirect.NORMAL表示对除HTTPS到HTTP之外的重定向进行自动跟随 |
connectTimeout(Duration) |
设置等待与服务器建立连接的最长时间 |
proxy(ProxySelector) |
配置代理服务器 |
HttpClient实例是不可变的,所有配置在构建后即固定,因此该实例可以安全地在多个线程间共享,并且内部自动维护连接池,以提升性能。
四、构建和发送请求
4.1 构建HttpRequest
HttpRequest同样采用构建器模式创建。以下是一个GET请求的示例:
1 | package com.johnson.example.httpclient; |
4.2 发送请求并处理响应
发送请求主要通过HttpClient的两个核心方法:
send(HttpRequest, BodyHandler):同步方式。调用线程将被阻塞,直到收到完整响应。sendAsync(HttpRequest, BodyHandler):异步方式。立即返回CompletableFuture<HttpResponse>,响应到达时自动完成该Future。
两个方法均需要传入一个BodyHandler参数,用于指定如何解析响应体。
4.3 同步请求示例
1 | package com.johnson.example.httpclient; |
4.4 异步请求示例
1 | package com.johnson.example.httpclient; |
五、BodyHandler与BodyPublisher详解
5.1 响应体处理(BodyHandler)
HttpResponse.BodyHandler用于将响应体转换为特定类型。BodyHandlers工具类提供了多种预定义的处理器:
| 方法 | 返回类型 | 适用场景 |
|---|---|---|
ofString() |
String |
将响应体读取为字符串 |
ofBytes() |
byte[] |
将响应体读取为字节数组 |
ofFile(Path) |
Path |
将响应体直接写入文件 |
ofInputStream() |
InputStream |
以流式方式处理响应体,适合大文件下载 |
ofLines() |
Stream<String> |
按行流式读取响应体,适合处理大文本数据 |
discarding() |
Void |
忽略响应体,仅关注状态码和响应头 |
5.2 请求体发布(BodyPublisher)
发送POST、PUT等需要携带请求体的请求时,使用HttpRequest.BodyPublisher来提供请求体内容。BodyPublishers工具类提供了多种预定义的发布器:
1 | // POST请求示例 |
| 方法 | 适用场景 |
|---|---|
ofString(String) |
发送字符串格式的请求体(如JSON、XML、纯文本) |
ofBytes(byte[]) |
发送字节数组 |
ofFile(Path) |
从文件读取内容作为请求体 |
ofInputStream(Supplier<InputStream>) |
从输入流读取请求体 |
noBody() |
发送无请求体的请求(GET、DELETE默认使用) |
六、同步与异步编程模式
6.1 模式对比
| 维度 | 同步(send) | 异步(sendAsync) |
|---|---|---|
| 线程行为 | 调用线程阻塞,等待响应返回 | 调用线程立即返回,不阻塞 |
| 返回值 | HttpResponse<T> |
CompletableFuture<HttpResponse<T>> |
| 适用场景 | 批量处理、简单请求、脚本类任务 | 高并发、微服务间调用、UI响应式编程 |
| 错误处理 | 使用try-catch捕获异常 |
通过exceptionally()或handle()处理 |
6.2 异步请求的并发组合
CompletableFuture提供了丰富的组合能力,可以轻松实现多个异步请求的并发执行或串行编排:
1 | package com.johnson.example.httpclient; |
七、HTTP/2特性
从Java 11开始,HttpClient默认支持HTTP/2协议。当服务器和TLS层通过ALPN(Application-Layer Protocol Negotiation)协商支持HTTP/2时,客户端将利用HTTP/2的多路复用能力——在单个TCP连接上同时传输多个请求,这显著降低了微服务架构或高并发场景中的网络延迟。
值得注意的是,若要实际使用HTTP/2 over TLS,服务器端也需要相应配置。例如,Tomcat 9.0.1及以上版本默认启用HTTP/2,且需要配置TLS支持。若服务器不支持HTTP/2,客户端会自动回退到HTTP/1.1。
八、WebSocket客户端支持
除了HTTP请求处理之外,HttpClient还内置了WebSocket客户端支持。通过HttpClient.newWebSocketBuilder()方法可以创建WebSocket连接:
1 | package com.johnson.example.httpclient; |
WebSocket支持使得实现实时双向通信(如聊天应用、实时仪表盘、事件流等)无需引入第三方依赖,即可与Java标准库无缝集成。
九、小结
JDK 11引入的标准化HTTP Client API为Java开发者带来了久违的现代化HTTP通信体验。快速回顾其核心特性:
| 特性 | 说明 |
|---|---|
| 无需第三方依赖 | 属于Java标准库,开箱即用 |
| HTTP/2原生支持 | 自动协商与回退,多路复用提升性能 |
| 同步与异步双模式 | send()用于阻塞场景,sendAsync()配合CompletableFuture应对高并发 |
| 流畅的构建器API | HttpClient、HttpRequest均采用构建器模式,配置直观 |
| 灵活的响应/请求体处理 | BodyHandlers和BodyPublishers提供多种内置处理器 |
| 内置WebSocket客户端 | newWebSocketBuilder()支持全双工实时通信 |
如果你的项目已经升级到JDK 11或更高版本,建议在需要发送HTTP请求的场景中优先使用java.net.http.HttpClient,让代码更加简洁、健壮且易于维护。
如果需要进一步了解本文涉及的各类API的更多细节,可以参考 Oracle官方文档 中的相关内容。

