下面我将为你提供一个从入门到精通的完整指南,涵盖:

- 基础入门:创建
HttpClient、发送 GET/POST 请求、处理响应。 - 进阶用法:设置请求头、处理请求体(JSON, Form)、添加超时、处理认证。
- 异步请求:如何非阻塞地发送请求。
- 与第三方库(如 Apache HttpClient)的对比。
基础入门
1 创建 HttpClient
HttpClient 是一个可重用的对象,最佳实践是创建一个实例并在整个应用程序中共享它。
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Duration;
public class HttpClientBasicExample {
public static void main(String[] args) throws Exception {
// 1. 创建 HttpClient 实例
// 可以配置连接超时、版本等
HttpClient client = HttpClient.newBuilder()
.version(HttpClient.Version.HTTP_2) // 使用 HTTP/2
.connectTimeout(Duration.ofSeconds(10)) // 连接超时 10 秒
.build();
// 2. 创建 HttpRequest 请求对象
// GET 请求示例:获取 JSONPlaceholder 的用户信息
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://jsonplaceholder.typicode.com/users/1"))
.header("Accept", "application/json") // 设置 Accept 头
.GET() // 显式指定 GET 方法
.build();
// 3. 发送请求并获取响应
// 同步发送,会阻塞当前线程
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
// 4. 处理响应
System.out.println("响应状态码: " + response.statusCode());
System.out.println("响应头 Content-Type: " + response.headers().firstValue("Content-Type").orElse("N/A"));
System.out.println("响应体:");
System.out.println(response.body());
}
}
运行结果:
响应状态码: 200
响应头 Content-Type: application/json; charset=utf-8
响应体:
{
"id": 1,
"name": "Leanne Graham",
"username": "Bret",
"email": "Sincere@april.biz",
"address": {
"street": "Kulas Light",
"suite": "Apt. 556",
"city": "Gwenborough",
"zipcode": "92998-3874",
"geo": {
"lat": "-37.3159",
"lng": "81.1496"
}
},
"phone": "1-770-736-8031 x56442",
"website": "hildegard.org",
"company": {
"name": "Romaguera-Crona",
"catchPhrase": "Multi-layered client-server neural-net",
"bs": "harness real-time e-markets"
}
}
2 发送 POST 请求
发送 POST 请求通常需要包含请求体,下面是一个发送 JSON 数据的例子。
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Duration;
import java.util.Map;
public class HttpClientPostExample {
public static void main(String[] args) throws Exception {
HttpClient client = HttpClient.newBuilder().build();
// 1. 准备要发送的 JSON 数据
String jsonBody = "{\n" +
" \"title\": \"foo\",\n" +
" \"body\": \"bar\",\n" +
" \"userId\": 1\n" +
"}";
// 2. 创建 POST 请求
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://jsonplaceholder.typicode.com/posts"))
.header("Content-Type", "application/json") // 设置 Content-Type 为 JSON
.POST(HttpRequest.BodyPublishers.ofString(jsonBody)) // 设置请求体
.build();
// 3. 发送请求并获取响应
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
// 4. 处理响应
System.out.println("响应状态码: " + response.statusCode());
System.out.println("响应体:");
System.out.println(response.body());
}
}
进阶用法
1 设置请求头
可以在 HttpRequest.Builder 中使用 header(key, value) 方法链式调用添加多个请求头。

HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://example.com/api"))
.header("User-Agent", "My-Java-App/1.0")
.header("Authorization", "Bearer your_token_here")
.header("Accept-Language", "en-US,en;q=0.9")
.GET()
.build();
2 处理不同的请求体
除了 String,HttpClient 还支持多种请求体类型:
- 字节数组:
HttpRequest.BodyPublishers.ofByteArray(byte[] bytes) - 文件:
HttpRequest.BodyPublishers.ofPath(Path path) - 输入流:
HttpRequest.BodyPublishers.ofInputStream(Supplier<InputStream> inputStreamSupplier)
3 设置超时
有两种超时需要考虑:
- 连接超时:建立连接的超时时间,在创建
HttpClient时设置。 - 请求超时:从发送请求到接收完整响应的超时时间,在发送请求时设置。
HttpClient client = HttpClient.newBuilder()
.connectTimeout(Duration.ofSeconds(10))
.build();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://example.com/slow-api"))
.timeout(Duration.ofSeconds(30)) // 整个请求(包括读取响应体)超时 30 秒
.GET()
.build();
4 处理认证
HttpClient 内置了对基本认证和摘要认证的支持。
import java.net.Authenticator;
import java.net.PasswordAuthentication;
// 在发送请求前,设置全局的 Authenticator
Authenticator.setDefault(new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
// 如果请求的站点是需要认证的,这个方法会被调用
if (getRequestingHost().equals("protected-site.com")) {
return new PasswordAuthentication("username", "password".toCharArray());
}
return null;
}
});
// 然后像平常一样发送请求
HttpClient client = HttpClient.newBuilder().build();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://protected-site.com/secure-data"))
.GET()
.build();
异步请求
异步请求不会阻塞调用线程,它依赖于 CompletableFuture 来处理结果。

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 HttpClientAsyncExample {
public static void main(String[] args) throws Exception {
HttpClient client = HttpClient.newBuilder().build();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://jsonplaceholder.typicode.com/users/1"))
.build();
// 发送异步请求,返回一个 CompletableFuture
CompletableFuture<HttpResponse<String>> futureResponse = client.sendAsync(request, HttpResponse.BodyHandlers.ofString());
// 定义响应处理逻辑
futureResponse.thenAccept(response -> {
System.out.println("异步请求完成,状态码: " + response.statusCode());
System.out.println("响应体: " + response.body());
}).exceptionally(e -> {
System.err.println("异步请求发生错误: " + e.getMessage());
return null;
});
System.out.println("异步请求已发送,主线程继续执行其他任务...");
// 为了让主线程等待异步任务完成(仅用于演示)
// 在真实应用中,主线程不应该等待异步任务
Thread.sleep(2000);
}
}
与 Apache HttpClient 的对比
虽然 Java 11+ 的 HttpClient 已经非常强大,但 Apache HttpClient 仍然在许多项目中广泛使用。
| 特性 | Java 11+ HttpClient |
Apache HttpClient (4.x / 5.x) |
|---|---|---|
| 依赖 | JDK 标准库,无需额外依赖 | 需要添加 Maven/Gradle 依赖 |
| API 风格 | 现代、函数式、Builder 模式 | 经典、面向对象 |
| 异步支持 | 基于 CompletableFuture,非常现代 |
基于 Future 和 AsyncCallback,成熟 |
| HTTP/2 | 原生支持 | 需要额外配置或使用 5.x 版本 |
| 可配置性 | 良好,但相对简单 | 极高,连接池、路由、重试策略等配置非常灵活 |
| 社区与生态 | 由 Oracle 维护,是 Java 未来的方向 | 由 Apache 基金会维护,历史悠久,生态非常成熟 |
| 学习曲线 | 相对平缓 | 较陡峭,因为配置项非常多 |
- 新项目或使用最新 JDK 的项目:优先选择 Java 11+
HttpClient,它更轻量、更符合 Java 生态的未来趋势,API 设计也更优雅。 - 遗留项目或需要复杂配置的项目:如果项目已经深度集成了 Apache HttpClient,或者需要其高度可配置的特性(如非常精细的连接池管理),继续使用 Apache HttpClient 是一个合理的选择。
Maven 依赖(如果需要使用 Apache HttpClient)
如果你因某些原因需要使用 Apache HttpClient,可以在 pom.xml 中添加以下依赖:
<!-- Apache HttpClient 5.x (推荐) -->
<dependency>
<groupId>org.apache.httpcomponents.client5</groupId>
<artifactId>httpclient5</artifactId>
<version>5.3.1</version> <!-- 请使用最新版本 -->
</dependency>
<!-- 对应的 HTTP/5 支持 -->
<dependency>
<groupId>org.apache.httpcomponents.core5</groupId>
<artifactId>httpcore5</artifactId>
<version>5.2</version> <!-- 请使用最新版本 -->
</dependency>
希望这份详细的指南能帮助你熟练掌握 Java 中的 HTTP 请求!
