提到 HttpClient 这个类,大家并不陌生,都曾经用过。但为什么 JDK11 中又出现了这个类呢。
原因很简单,我们在 JDK11 版本之前使用的 HttpClient 来自于第三方框架,并不是 JDK 的原生类。
在既不使用第三方框架,又没有 HttpClient 类的时候,只有 HttpURLConnection 可以使用,这个类使用起来比较复杂,功能也较为有限。
一、为什么需要HttpClient?
JDK8及之前版本,Java使用HttpURLConnection来处理HTTP请求,这个类存在一些问题:
使用复杂
HttpURLConnection的使用流程繁琐,错误处理麻烦。
功能受限
不支持现代HTTP/2协议、不方便处理异步请求等。
HttpClient应运而生,目的是提供一个现代化的、功能完备的HTTP客户端,支持HTTP/2和异步编程,使得网络编程变得更简单、更高效。
二、HttpClient能解决什么问题?
简化HTTP通信
提供一套简单的API,使得发送HTTP请求和接收响应更加直观。
支持现代协议HTTP/2
HTTP/2支持多个请求在同一连接并行传输,提高了通信效率。
异步支持
可以非阻塞地处理HTTP请求,提高应用程序的性能和响应速度。
自动化的资源管理
例如自动关闭连接,减少内存泄漏的风险。
三、 HttpClient的特点
易用性
提供了流畅的API,使得创建和发送HTTP请求变得非常简单。
异步和同步支持
可以根据需要选择使用同步还是异步方式发送请求。
自动重连和请求重试
在网络不稳定时自动处理重连和重试,减轻开发者的负担。
性能优化
通过支持HTTP/2,减少了延迟和提高了吞吐量。
四、繁琐的HttpURLConnection
在 JDK 8 之前,Java 提供的标准方式是通过 HttpURLConnection 来发送 HTTP 请求。
虽然功能完备,但它的使用方式相对繁琐,尤其是需要手动处理请求的各种细节,比如设置请求头、处理输入输出流等。
假设我们想要向一个网站发送一个 POST 请求,并提交一些数据,看看 JDK 8 中 HttpURLConnection 的写法:
示例代码(JDK 8 中的 HttpURLConnection):
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
publicclass HttpURLConnectionExample {
public static void main(String[] args) {
try {
// 创建一个 URL 对象
URL url = new URL("https://jsonplaceholder.typicode.com/posts");
// 打开 HTTP 连接
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
// 设置请求方法为 POST
connection.setRequestMethod("POST");
// 设置请求头
connection.setRequestProperty("Content-Type", "application/json");
// 允许输出流,意味着我们将发送请求体数据
connection.setDoOutput(true);
// 准备请求体数据
String requestBody = "{\"title\": \"foo\", \"body\": \"bar\", \"userId\": 1}";
// 向服务器发送请求体
try (OutputStream os = connection.getOutputStream()) {
os.write(requestBody.getBytes());
os.flush();
}
// 获取响应代码,通常 200 表示成功
int responseCode = connection.getResponseCode();
System.out.println("Response Code: " + responseCode);
// 读取响应内容
try (BufferedReader br = new BufferedReader(
new InputStreamReader(connection.getInputStream()))) {
StringBuilder response = new StringBuilder();
String line;
while ((line = br.readLine()) != null) {
response.append(line);
}
System.out.println("Response Body: " + response);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
关键步骤:
创建一个URL对象,并打开连接。
设置请求方法、请求头等信息。
通过OutputStream发送请求体数据。
使用BufferedReader读取服务器的响应数据。
虽然上面的代码能够完成基本的 HTTP 请求,但是它有几个缺点:
代码量比较多,涉及到大量的流操作;
手动管理连接、输出流和输入流比较容易出错;
不支持现代的 HTTP 协议(如 HTTP/2)。
可以看出,使用 HttpURLConnection 发起 HTTP 请求显得有些“繁琐”。
五、简洁的 HttpClient
随着 Java 语言的发展,JDK 11 引入了新的 HTTP 客户端 API,名为 HttpClient。
这个 API 不仅支持 HTTP/1.x,还原生支持 HTTP/2,甚至能够处理 WebSocket 请求。
相比于 HttpURLConnection,HttpClient 的 API 更加简洁,使用起来也更直观。它避免了许多冗余的细节,使得发 HTTP 请求变得更容易。
让我们来看一下 JDK11 中如何使用 HttpClient 来发送一个 HTTP 请求。
示例代码(JDK11 中的 HttpClient):
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
publicclass HttpClientExample {
public static void main(String[] args) {
try {
// 创建 HttpClient 实例
HttpClient client = HttpClient.newHttpClient();
// 创建 HTTP 请求
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://jsonplaceholder.typicode.com/posts"))
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString("{\"title\": \"foo\", \"body\": \"bar\", \"userId\": 1}"))
.build();
// 发送请求并获取响应
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
// 打印响应状态码和响应内容
System.out.println("Response Code: " + response.statusCode());
System.out.println("Response Body: " + response.body());
} catch (Exception e) {
e.printStackTrace();
}
}
}
关键步骤:
使用 HttpClient.newHttpClient() 创建HttpClient实例。
使用 HttpRequest.newBuilder() 构建 HTTP 请求,直接设置请求头、请求体等信息。
使用 client.send() 方法发送请求并获取响应。
可以看到,JDK 17 中的 HttpClient 使得 HTTP 请求变得更加简洁:
请求的构建过程更加直观,直接调用 HttpRequest.newBuilder() 设置请求的各项参数;
不需要手动管理输入输出流;
响应处理也更加简单。
六、HttpURLConnection vs HttpClient
七、HttpClient 技术的发展
JDK 8之前:HttpURLConnection是主要的HTTP通信工具,但API复杂、功能有限。
JDK 9:HttpClient作为实验性API引入,开始支持异步和HTTP/2协议。
JDK 11:HttpClient作为正式API发布,支持HTTP/2、异步请求,并简化了网络编程。
JDK 17及后续版本:持续优化性能和支持更多现代网络特性。
HttpClient的发展历程反映了Java在网络编程领域的不断进步,它从最初的基础功能逐步演化,支持现代网络协议、异步编程和高性能需求,成为开发者进行网络通信时不可或缺的工具之一。
java的net包有了 HttpClient 这个原生类,我们就再也不需要引入第三方架包了。
领取专属 10元无门槛券
私享最新 技术干货