本文目录导读:

HttpClient 是 Java 11 开始官方内置的一个强大且现代的 HTTP 客户端库,用于替代传统的 HttpURLConnection,它支持 HTTP/1.1、HTTP/2、WebSocket,并提供了同步和异步两种模式。
以下是详细的用法指南,分为环境要求、基本使用和高级特性。
环境要求与引入
- Java版本:需要 Java 11 或更高版本。
- 引入方式:不需要导入任何第三方依赖,它是
java.net.http包下的标准库。
import java.net.URI; import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse;
核心组件介绍
HttpClient:发送请求的客户端,可以单例复用,通常全局只创建一个。HttpRequest:描述要发送的请求(URL、请求头、请求体、HTTP方法)。HttpResponse<T>:描述服务器返回的响应(状态码、响应头、响应体)。
基本用法(同步 GET 请求)
这是最基础、最常见的用法。
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
public class HttpClientDemo {
public static void main(String[] args) throws Exception {
// 1. 创建一个 HttpClient 实例(通常是单例)
HttpClient client = HttpClient.newHttpClient();
// 2. 构建一个 GET 请求
HttpRequest request = HttpRequest.newBuilder()
.uri(new URI("https://api.github.com/users/octocat"))
// .header("User-Agent", "Java HttpClient") // 可选:设置请求头
.GET() // 显式指定方法,也可以不写(默认GET)
.build();
// 3. 发送请求,并接收响应(同步阻塞)
// HttpResponse.BodyHandlers.ofString() 表示将响应体转为字符串
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
// 4. 处理响应
System.out.println("Status Code: " + response.statusCode());
System.out.println("Headers: " + response.headers().map());
System.out.println("Body: " + response.body());
}
}
发送 POST 请求(带 JSON 请求体)
如果你需要向服务器提交数据。
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
public class HttpClientPostDemo {
public static void main(String[] args) throws Exception {
HttpClient client = HttpClient.newHttpClient();
// JSON 请求体
String jsonBody = "{\"name\": \"John\", \"age\": 30}";
HttpRequest request = HttpRequest.newBuilder()
.uri(new URI("https://httpbin.org/post"))
.header("Content-Type", "application/json") // 设置内容类型
.POST(HttpRequest.BodyPublishers.ofString(jsonBody)) // 发布请求体
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
异步请求(非阻塞)
如果你不想让当前线程等待网络请求,可以使用 sendAsync。
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.concurrent.CompletableFuture;
public class HttpClientAsyncDemo {
public static void main(String[] args) throws Exception {
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://httpbin.org/delay/5")) // 模拟延迟5秒
.GET()
.build();
// 发送异步请求,返回 CompletableFuture
CompletableFuture<HttpResponse<String>> future =
client.sendAsync(request, HttpResponse.BodyHandlers.ofString());
// 设置回调:当请求完成时打印结果
future.thenApply(HttpResponse::body)
.thenAccept(System.out::println);
// 可以做其他事情...
System.out.println("请求已经发出,主线程继续执行...");
// 等待异步任务完成(防止程序立即退出)
future.get();
}
}
处理不同类型的响应体
HttpResponse.BodyHandlers 提供了多种处理响应体的方式:
| 处理器方法 | 返回值类型 | 适用场景 |
|---|---|---|
ofString() |
String |
文本响应(HTML, JSON) |
ofByteArray() |
byte[] |
二进制数据(图片,文件) |
ofInputStream() |
InputStream |
大文件流式下载 |
ofFile(Path) |
Path |
直接保存到文件 |
discarding() |
Void |
不关心响应体 |
示例:下载图片到文件
import java.nio.file.Path;
import java.net.http.HttpResponse;
// ... 省略 client 和 request 构建
HttpResponse<Path> response = client.send(request,
HttpResponse.BodyHandlers.ofFile(Path.of("image.png")));
System.out.println("图片已保存到: " + response.body());
设置超时与代理
构建 HttpClient 和 HttpRequest 时可以配置超时。
import java.time.Duration;
import java.net.ProxySelector;
import java.net.InetSocketAddress;
HttpClient client = HttpClient.newBuilder()
.connectTimeout(Duration.ofSeconds(10)) // 连接超时
.proxy(ProxySelector.of(new InetSocketAddress("proxy.example.com", 8080))) // 代理设置
.followRedirects(HttpClient.Redirect.NORMAL) // 自动重定向
.build();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://example.com"))
.timeout(Duration.ofSeconds(30)) // 请求超时(读取超时)
.GET()
.build();
常见错误与注意事项
- URI 格式:需要使用
URI对象,而不是字符串,注意 URI 必须是绝对路径(包含协议头http://或https://)。 - 异常处理:
send()会抛出IOException(网络问题)和InterruptedException。sendAsync()的CompletableFuture会包含ExecutionException。
- HTTP/2 支持:
HttpClient默认优先使用 HTTP/2,如果服务器不支持,会降级到 HTTP/1.1,这是自动的。 - 复用 HttpClient:
HttpClient是线程安全的,建议在整个应用中使用单例,而不是每次请求都创建新的实例。 - Cookie 管理:默认不存储 Cookie,如果需要,可以在构建
HttpClient时设置CookieManager。
- 同步:
send(),简单直接,适合快速开发。 - 异步:
sendAsync()+CompletableFuture,适合高并发、非阻塞场景。 - Builder 模式:
HttpClient.newBuilder()和HttpRequest.newBuilder()用于灵活配置。
如果还有特定场景(比如文件上传、WebSocket 连接)的需求,可以进一步提问。