java.net.http.HttpClient
发送同步请求
java.net.http.HttpClient 是 CoddyKit 上的免费 Java Academy 课时。 这是第 1 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Java Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Java Academy 课程共包含 4 节课。
现代 HTTP 客户端
从 Java 11 开始,JDK 在 java.net.http 包中提供了现代 HTTP 客户端。它用简洁、流畅的 API 替代了旧的 HttpURLConnection,并支持 HTTP/1.1 和 HTTP/2。
三个核心类型是:
- HttpClient — 发送请求并管理配置(超时、代理、重定向)。
- HttpRequest — 对要发送内容的不可变描述。
- HttpResponse — 响应结果,包括状态、标头和正文。
创建 HttpClient
您可以使用静态 newBuilder() 方法构建客户端。一个客户端可以重复用于发送多个请求,并且是线程安全的。
这里我们将 HTTP/2 和连接超时配置好。要快速创建默认实例,也可以使用 newHttpClient()。
import java.net.http.HttpClient;
import java.time.Duration;
public class Main {
public static void main(String[] args) {
HttpClient client = HttpClient.newBuilder()
.version(HttpClient.Version.HTTP_2)
.connectTimeout(Duration.ofSeconds(10))
.build();
System.out.println("Client version: " + client.version());
}
}构建请求
HttpRequest 是不可变的,并通过流式构建器构建。至少需要提供一个 URI;默认情况下,它会执行 GET。
您可以使用 URI.create(...) 将字符串转换为 URI。
import java.net.URI;
import java.net.http.HttpRequest;
public class Main {
public static void main(String[] args) {
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://example.com/data"))
.GET()
.build();
System.out.println("Method: " + request.method());
System.out.println("URI: " + request.uri());
}
}同步发送
send 方法会阻塞调用线程,直到收到响应。它需要一个 BodyHandler,用于告知客户端如何解释响应正文。
BodyHandlers.ofString() 会将正文读入 String。
import java.net.URI;
import java.net.http.*;
public class Main {
public static void main(String[] args) throws Exception {
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://example.com"))
.build();
HttpResponse<String> response =
client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println("Status: " + response.statusCode());
}
}读取状态码
响应通过 statusCode() 提供一个 int 类型的状态码。2xx 范围内的代码表示成功,3xx 表示重定向,4xx 表示客户端错误,5xx 表示服务器错误。
请注意:HTTP 客户端不会因 4xx/5xx 响应抛出异常——您必须自行检查状态码。
public class Main {
public static void main(String[] args) {
int status = 404;
String label;
if (status >= 200 && status < 300) label = "Success";
else if (status >= 300 && status < 400) label = "Redirect";
else if (status >= 400 && status < 500) label = "Client error";
else label = "Server error";
System.out.println(status + " -> " + label);
}
}读取正文
使用 BodyHandlers.ofString() 时,response.body() 会返回一个 String。此外还有用于字节、文件和流的其他处理器(稍后介绍)。
此代码片段模拟了您会收到的正文内容。
public class Main {
public static void main(String[] args) {
String body = "{\"message\":\"hello\"}";
System.out.println("Body length: " + body.length());
System.out.println("Body: " + body);
}
}处理重定向
默认情况下,客户端不会跟随重定向。您可以通过构建器上的 followRedirects(...) 进行配置。
HttpClient.Redirect 中的选项包括 NEVER、ALWAYS 和 NORMAL(除从 HTTPS 降级到 HTTP 的情况外均会跟随)。
import java.net.http.HttpClient;
public class Main {
public static void main(String[] args) {
HttpClient client = HttpClient.newBuilder()
.followRedirects(HttpClient.Redirect.NORMAL)
.build();
System.out.println("Redirect policy: " + client.followRedirects());
}
}为每个请求设置超时
连接超时设置在客户端上。请求超时(等待响应的时长)则通过请求上的 timeout(...) 设置。
如果超时,请求会抛出 HttpTimeoutException。
import java.net.URI;
import java.net.http.HttpRequest;
import java.time.Duration;
public class Main {
public static void main(String[] args) {
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://example.com"))
.timeout(Duration.ofSeconds(5))
.build();
System.out.println("Timeout set: " + request.timeout().isPresent());
}
}检查响应头
响应包含一个可通过 headers() 访问的 HttpHeaders 对象。请求头查找不区分大小写,并且可能返回多个值,因此 firstValue(...) 会返回一个 Optional<String>。
import java.util.Optional;
public class Main {
public static void main(String[] args) {
// Simulating a header lookup result
Optional<String> contentType = Optional.of("application/json");
System.out.println("Content-Type: " + contentType.orElse("unknown"));
}
}受检异常
同步 send 会声明两个受检异常:
- 输入/输出异常 — 网络或协议失败。
- InterruptedException — 被阻塞的线程遭到中断。
您必须捕获或声明这两个异常。异步调用(下一课)会通过返回异步结果对象来避免这一点。
import java.io.IOException;
public class Main {
public static void main(String[] args) {
try {
// client.send(...) would go here
throw new IOException("connection refused");
} catch (IOException e) {
System.out.println("Network problem: " + e.getMessage());
}
}
}可复用的客户端
最佳实践:创建一个 HttpClient,并在整个应用中复用它。它会复用连接,并且完全支持线程安全。
每次请求都创建新客户端会浪费资源,也会使 HTTP/2 多路复用失去作用。
import java.net.http.HttpClient;
public class Main {
private static final HttpClient SHARED = HttpClient.newHttpClient();
public static void main(String[] args) {
System.out.println("Shared client ready: " + (SHARED != null));
}
}快速检查
测试您对同步 HTTP 客户端的理解。
回顾
您已经学习了 JDK HTTP 客户端的基础知识:
- HttpClient.newBuilder() 用于配置版本、超时和重定向;请复用同一个实例。
- HttpRequest.newBuilder().uri(...).GET() 用于构建不可变请求。
- client.send(request, BodyHandlers.ofString()) 会阻塞并返回一个
HttpResponse<String>。 - 使用
statusCode()、body()和headers()读取结果。 - 非 2xx 状态码不会抛出异常——请自行检查。
常见问题解答
「java.net.http.HttpClient」课时是免费的吗?
是的 — 「java.net.http.HttpClient」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Java Academy 课程的其余内容,请升级到 CoddyKit PRO。 Java Academy 课程共包含 4 节课。
「java.net.http.HttpClient」这节课中我会学到什么?
发送同步请求 你通过在浏览器中直接运行的动手代码来练习 Java Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 Java Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 Java Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 1 节课,共 4 节。
「java.net.http.HttpClient」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 Java Academy 课中编写并运行代码吗?
能。每节 Java Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。