Java HttpClient
最后修改日期:2025年4月17日
本 Java HttpClient 教程演示了如何在 Java 中使用 HttpClient 库来创建 HTTP 请求。它涵盖了构建简单的 GET 和 POST 请求,以及处理查询参数、异步请求、表单数据和超时等高级示例,为进行 HTTP 调用提供了全面的指南。
HTTP
超文本传输协议(HTTP)是一种无状态的应用层协议,专为分布式、协作式、超媒体信息系统而设计。它支撑着万维网上的数据通信,使客户端(如 Web 浏览器或应用程序)能够从服务器请求资源并接收响应。HTTP 支持多种方法,如 GET、POST、PUT 和 DELETE,从而促进了各种操作,例如检索网页、提交表单或更新服务器数据。
在本教程中,我们使用 httpbin.org
,这是一个免费的开源 HTTP 请求和响应服务,提供了用于测试各种 HTTP 操作(包括重定向、身份验证和数据操作)的端点。此外,我们还利用 webcode.me
,这是一个专为测试 HTTP 请求而设计的轻量级 HTML 页面,为我们的示例提供了一个简单可靠的目标。
方法 | 描述 | 常见用例 | 幂等 |
---|---|---|---|
GET |
请求指定资源的表示形式,而不修改它。 | 检索网页、获取 API 数据、访问图像或文件。 | 是 |
POST |
向服务器提交数据以创建或更新资源。 | 提交表单、上传文件、创建新的数据库记录。 | 否 |
PUT |
用提供的数据替换或更新资源。 | 更新用户个人资料、替换文件、修改 API 资源。 | 是 |
DELETE |
从服务器中删除指定的资源。 | 删除用户帐户、移除数据库条目、擦除文件。 | 是 |
HEAD |
请求资源的头部信息,而不检索其主体。 | 检查资源元数据、验证链接有效性、测试服务器响应。 | 是 |
HTTP 中的幂等性指的是某些方法的属性,即多次重复相同的请求会产生相同的结果,而不会在服务器上产生额外的副作用。幂等方法(如 GET、PUT、DELETE 和 HEAD)确保后续相同的请求不会在初始请求之外改变服务器的状态,这使得它们在出现网络问题时可以安全重试。相比之下,像 POST 这样的非幂等方法每次都可能创建新资源,每次请求都会影响服务器的状态。
HttpClient
在 Java 11 中引入的 HttpClient
库提供了一个现代、灵活且功能强大的 API,用于在 Java 中发出 HTTP 请求。在 Java 11 之前,开发人员通常使用功能简陋的 URLConnection
类(它缺乏高级功能),或者依赖于像 Apache HttpClient 或 OkHttp 这样的第三方库来实现健壮的 HTTP 通信。内置的 HttpClient
通过流线型的链式 API 和对同步及异步请求的原生支持,简化了 HTTP 操作。
Java HttpClient
支持 HTTP/1.1 和 HTTP/2 协议,默认使用 HTTP/2 以通过多路复用和头部压缩等特性获得更好的性能。如果服务器不支持 HTTP/2,客户端会自动降级到 HTTP/1.1,以确保兼容性。此外,HttpClient
提供了重定向处理、身份验证和超时等高级功能,使其成为现代 Web 交互的多功能工具。
client = HttpClient.newHttpClient(); client = HttpClient.newBuilder().build();
您可以通过两种方式创建 HttpClient
实例:使用 newHttpClient
创建具有默认设置的客户端,或使用 newBuilder
创建可自定义的客户端,您可以在其中配置超时、重定向策略或代理设置等选项。这些方法为构建满足您应用程序需求的 HTTP 请求提供了基础。
HttpClient 状态
在第一个示例中,我们检查一个网页的状态。
import java.io.IOException; import java.net.URI; import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; void main() throws IOException, InterruptedException { try (HttpClient client = HttpClient.newHttpClient()) { HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://webcode.me")) .GET() // GET is default .build(); HttpResponse<Void> response = client.send(request, HttpResponse.BodyHandlers.discarding()); System.out.println(response.statusCode()); } }
此示例创建一个到 webcode.me
网站的 GET 请求并检索 HTTP 响应。我们从响应中提取状态码。
HttpClient client = HttpClient.newHttpClient();
创建了一个新的 HttpClient
实例。
HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("http://webcode.me")) .GET() // GET is default .build();
构造了一个新的 HttpRequest
。我们指定了 URI
和请求方法。(如果未指定方法,则默认使用 GET。)
HttpResponseresponse = client.send(request, HttpResponse.BodyHandlers.discarding());
我们发送请求。由于我们对响应主体不感兴趣,我们使用 HttpResponse.BodyHandlers.discarding
将其丢弃。
System.out.println(response.statusCode());
我们使用 statusCode
方法检索状态码。
HEAD 请求
HEAD 请求是一种没有消息主体的 GET 请求。
import java.io.IOException; import java.net.URI; import java.net.http.HttpClient; import java.net.http.HttpHeaders; import java.net.http.HttpRequest; import java.net.http.HttpResponse; void main() throws IOException, InterruptedException { try (HttpClient client = HttpClient.newHttpClient()) { var request = HttpRequest.newBuilder(URI.create("https://webcode.me")) .method("HEAD", HttpRequest.BodyPublishers.noBody()) .build(); HttpResponse<Void> response = client.send(request, HttpResponse.BodyHandlers.discarding()); HttpHeaders headers = response.headers(); headers.map().forEach((key, values) -> { System.out.printf("%s: %s%n", key, values); }); } }
此示例构造一个 HEAD 请求。
var request = HttpRequest.newBuilder(URI.create("https://webcode.me")) .method("HEAD", HttpRequest.BodyPublishers.noBody()) .build();
我们创建一个 HEAD 请求。由于请求不包含主体,我们使用 HttpRequest.BodyPublishers.noBody
。
HttpResponseresponse = client.send(request, HttpResponse.BodyHandlers.discarding());
我们发送请求并接收响应。
HttpHeaders headers = response.headers(); headers.map().forEach((key, values) -> { System.out.printf("%s: %s%n", key, values); });
我们从响应中获取头部信息并在控制台上显示它们。
$ java Main.java accept-ranges: [bytes] connection: [keep-alive] content-length: [395] content-type: [text/html] date: [Wed, 09 Oct 2024 13:22:09 GMT] etag: ["64f33c9f-18b"] last-modified: [Sat, 02 Sep 2023 13:46:07 GMT] server: [nginx/1.18.0 (Ubuntu)]
GET 请求
HTTP GET 方法请求指定资源的表示形式。使用 GET 的请求应该只用于检索数据。
import java.io.IOException; import java.net.URI; import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; void main() throws IOException, InterruptedException { try (HttpClient client = HttpClient.newHttpClient()) { HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://webcode.me")) .build(); HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body()); } }
我们生成一个到 webcode.me
网页的 GET 请求。
try (HttpClient client = HttpClient.newHttpClient()) {
使用 newHttpClient
工厂方法实例化一个新的 HttpClient
。
HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://webcode.me")) .build();
我们构造一个到该网页的同步请求。默认方法是 GET。
HttpResponseresponse = client.send(request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body());
我们发送请求,检索响应内容,并将其打印到控制台。我们使用 HttpResponse.BodyHandlers.ofString
,因为我们期望得到一个 HTML 字符串响应。
文件 BodyHandler
通过文件 body handler,我们可以方便地将响应文本保存到文件中。
import java.io.IOException; import java.net.URI; import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.nio.file.Path; import java.nio.file.Paths; void main() throws IOException, InterruptedException { try (HttpClient client = HttpClient.newHttpClient()) { HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://webcode.me")) .GET() // GET is default .build(); String fileName = "src/main/resources/index.html"; HttpResponse<Path> response = client.send(request, HttpResponse.BodyHandlers.ofFile(Paths.get(fileName))); System.out.println(response.statusCode()); } }
此示例将 HTML 页面保存到 src/main/resources/index.html
。
String fileName = "src/main/resources/index.html"; HttpResponse<Path> response = client.send(request, HttpResponse.BodyHandlers.ofFile(Paths.get(fileName)));
文件 body handler 是使用 HttpResponse.BodyHandlers.ofFile
创建的。
POST 请求
HTTP POST 方法将数据传输到服务器。它通常用于上传文件或提交已完成的 Web 表单。
<dependency> <groupId>com.google.code.gson</groupId> <artifactId>gson</artifactId> <version>2.11.0</version> </dependency>
我们需要 gson
依赖项。
import com.google.gson.Gson; import java.io.IOException; import java.net.URI; import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.util.HashMap; void main() throws IOException, InterruptedException { var values = new HashMap<String, String>() {{ put("name", "John Doe"); put("occupation", "gardener"); }}; Gson gson = new Gson(); String requestBody = gson.toJson(values); try (HttpClient client = HttpClient.newHttpClient()) { HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://httpbin.org/post")) .POST(HttpRequest.BodyPublishers.ofString(requestBody)) .build(); HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body()); } }
我们向 https://httpbin.org/post
页面发送一个 POST 请求。
var values = new HashMap<String, String>() {{ put("name", "John Doe"); put("occupation", "gardener"); }}; Gson gson = new Gson(); String requestBody = gson.toJson(values);
首先,我们使用 Gson
构造请求主体。
try (HttpClient client = HttpClient.newHttpClient()) { HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://httpbin.org/post")) .POST(HttpRequest.BodyPublishers.ofString(requestBody)) .build(); ... }
我们创建 POST 请求。通过 BodyPublishers.ofString
,我们生成一个新的 BodyPublisher
。它将高级 Java 对象转换为适合作为请求主体发送的字节缓冲区流。
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body());
我们发送请求并检索响应。
HttpClient 重定向
重定向涉及将一个 URL 转发到另一个 URL。HTTP 响应状态码 301 Moved Permanently 表示永久 URL 重定向,而 302 Found 表示临时重定向。
import java.io.IOException; import java.net.URI; import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; // toggle HttpClient.Redirect.ALWAYS / HttpClient.Redirect.NEVER void main() throws IOException, InterruptedException { try (HttpClient client = HttpClient.newBuilder() .followRedirects(HttpClient.Redirect.ALWAYS).build()) { HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://httpbin.org/redirect/3")) .GET() .build(); HttpResponse<Void> response = client.send(request, HttpResponse.BodyHandlers.discarding()); System.out.println(response.statusCode()); } }
在此示例中,我们发送一个被重定向的请求。
try (HttpClient client = HttpClient.newBuilder() .followRedirects(HttpClient.Redirect.ALWAYS).build()) { ... }
要配置重定向,我们使用 followRedirects
方法。
HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://httpbin.org/redirect/3")) .GET() .build();
URL https://httpbin.org/redirect/3
是一个测试端点,它会将请求重定向三次。
HttpResponseresponse = client.send(request, HttpResponse.BodyHandlers.discarding()); System.out.println(response.statusCode());
请求被发送,并显示响应状态。
HttpClient 读取 Favicon
以下示例从网站检索一个小图像。
import java.io.IOException; import java.net.URI; import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; void main() throws IOException, InterruptedException { try (HttpClient client = HttpClient.newHttpClient()) { HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://webcode.me/favicon.ico")) .build(); HttpResponse<byte[]> response = client.send(request, HttpResponse.BodyHandlers.ofByteArray()); byte[] data = response.body(); int i = 0; for (byte c : data) { System.out.printf("%02x ", c); i++; if (i % 10 == 0) { System.out.println(); } } } }
此示例从一个网站获取一个 favicon,并以十六进制格式打印其内容。
HttpResponse<byte[]> response = client.send(request, HttpResponse.BodyHandlers.ofByteArray());
使用 HttpResponse.BodyHandlers.ofByteArray
,我们读取二进制数据。
byte[] data = response.body();
我们从响应主体中提取字节数组。
int i = 0; for (byte c : data) { System.out.printf("%02x ", c); i++; if (i % 10 == 0) { System.out.println(); } }
在一个 for 循环中,我们以十六进制格式打印这些字节。
带查询参数的 GET 请求
此示例演示如何在 GET 请求中包含查询参数。
import java.io.IOException; import java.net.URI; import java.net.URLEncoder; import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.nio.charset.StandardCharsets; void main() throws IOException, InterruptedException { String query = "name=" + URLEncoder.encode("John Doe", StandardCharsets.UTF_8) + "&occupation=" + URLEncoder.encode("gardener", StandardCharsets.UTF_8); try (HttpClient client = HttpClient.newHttpClient()) { HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://httpbin.org/get?" + query)) .GET() .build(); HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body()); } }
此示例向 https://httpbin.org/get
发送一个带查询参数的 GET 请求。
String query = "name=" + URLEncoder.encode("John Doe", StandardCharsets.UTF_8) + "&occupation=" + URLEncoder.encode("gardener", StandardCharsets.UTF_8);
我们构造查询字符串,对参数进行编码以处理特殊字符。
HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://httpbin.org/get?" + query)) .GET() .build();
查询字符串被附加到 GET 请求的 URL 中。
异步 GET 请求
此示例展示了如何使用 HttpClient 执行异步 GET 请求。
import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; void main() { try (HttpClient client = HttpClient.newHttpClient()) { HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://webcode.me")) .GET() .build(); CompletableFuture<HttpResponse<String>> responseFuture = client.sendAsync(request, HttpResponse.BodyHandlers.ofString()); responseFuture.thenAccept(response -> { System.out.println("Status Code: " + response.statusCode()); System.out.println("Body: " + response.body()); }).join(); } }
此示例发送一个异步 GET 请求,并在响应到达时处理它。
CompletableFuture<HttpResponse<String>> responseFuture = client.sendAsync(request, HttpResponse.BodyHandlers.ofString());
sendAsync
方法返回一个用于异步处理的 CompletableFuture
。
responseFuture.thenAccept(response -> { System.out.println("Status Code: " + response.statusCode()); System.out.println("Body: " + response.body()); }).join();
我们使用 thenAccept
处理响应,并用 join
等待完成。
带表单数据的 POST 请求
此示例演示如何发送带有表单数据的 POST 请求。
import java.io.IOException; import java.net.URI; import java.net.URLEncoder; import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.nio.charset.StandardCharsets; import java.util.HashMap; import java.util.Map; import java.util.stream.Collectors; void main() throws IOException, InterruptedException { Map<String, String> formData = new HashMap<>(); formData.put("username", "john_doe"); formData.put("email", "john@example.com"); String requestBody = formData.entrySet().stream() .map(entry -> URLEncoder.encode(entry.getKey(), StandardCharsets.UTF_8) + "=" + URLEncoder.encode(entry.getValue(), StandardCharsets.UTF_8)) .collect(Collectors.joining("&")); try (HttpClient client = HttpClient.newHttpClient()) { HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://httpbin.org/post")) .header("Content-Type", "application/x-www-form-urlencoded") .POST(HttpRequest.BodyPublishers.ofString(requestBody)) .build(); HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body()); } }
此示例向 https://httpbin.org/post
发送一个带有表单数据的 POST 请求。
String requestBody = formData.entrySet().stream() .map(entry -> URLEncoder.encode(entry.getKey(), StandardCharsets.UTF_8) + "=" + URLEncoder.encode(entry.getValue(), StandardCharsets.UTF_8)) .collect(Collectors.joining("&"));
我们将表单数据编码为 URL 编码的字符串。
.header("Content-Type", "application/x-www-form-urlencoded")
我们设置 Content-Type
头部以指示表单数据。
带超时的 HttpClient
此示例展示了如何为 HTTP 请求配置超时。
import java.io.IOException; import java.net.URI; import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.time.Duration; void main() throws InterruptedException { try (HttpClient client = HttpClient.newBuilder() .connectTimeout(Duration.ofSeconds(5)) .build()) { HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://httpbin.org/delay/10")) .timeout(Duration.ofSeconds(3)) .GET() .build(); try { HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body()); } catch (IOException e) { System.err.println("Request timed out: " + e.getMessage()); } } }
此示例设置了连接超时和请求超时,并处理超时异常。
try (HttpClient client = HttpClient.newBuilder() .connectTimeout(Duration.ofSeconds(5)) .build()) {
我们为客户端设置了 5 秒的连接超时。
.timeout(Duration.ofSeconds(3))
我们为请求设置了 3 秒的超时。
try { HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body()); } catch (IOException e) { System.err.println("Request timed out: " + e.getMessage()); }
我们捕获并处理超时异常。
PUT 请求
此示例演示如何发送 PUT 请求以更新服务器上的数据。
import com.google.gson.Gson; import java.io.IOException; import java.net.URI; import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.util.HashMap; void main() throws IOException, InterruptedException { var values = new HashMap<String, String>() {{ put("name", "Jane Doe"); put("occupation", "developer"); }}; Gson gson = new Gson(); String requestBody = gson.toJson(values); try (HttpClient client = HttpClient.newHttpClient()) { HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://httpbin.org/put")) .header("Content-Type", "application/json") .method("PUT", HttpRequest.BodyPublishers.ofString(requestBody)) .build(); HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body()); } }
此示例向 https://httpbin.org/put
发送一个带有 JSON 数据的 PUT 请求。
var values = new HashMap<String, String>() {{ put("name", "Jane Doe"); put("occupation", "developer"); }}; Gson gson = new Gson(); String requestBody = gson.toJson(values);
我们使用 Gson 为 PUT 请求创建一个 JSON 负载。
.header("Content-Type", "application/json")
我们设置 Content-Type
头部以指示 JSON 数据。
.method("PUT", HttpRequest.BodyPublishers.ofString(requestBody))
我们指定 PUT 方法,并在请求主体中包含 JSON 负载。
处理 JSON 响应
此示例展示了如何解析来自 GET 请求的 JSON 响应。
import com.google.gson.Gson; import com.google.gson.JsonObject; import java.io.IOException; import java.net.URI; import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; void main() throws IOException, InterruptedException { try (HttpClient client = HttpClient.newHttpClient()) { HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://httpbin.org/get")) .GET() .build(); HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString()); Gson gson = new Gson(); JsonObject jsonResponse = gson.fromJson(response.body(), JsonObject.class); String url = jsonResponse.get("url").getAsString(); System.out.println("Requested URL: " + url); } }
此示例发送一个 GET 请求并解析 JSON 响应以提取特定数据。
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
我们将响应主体检索为字符串。
Gson gson = new Gson(); JsonObject jsonResponse = gson.fromJson(response.body(), JsonObject.class);
我们使用 Gson 将响应主体解析为 JSON 对象。
String url = jsonResponse.get("url").getAsString(); System.out.println("Requested URL: " + url);
我们从 JSON 响应中提取并打印 "url" 字段。
自定义头部
此示例演示如何向 HTTP 请求添加自定义头部。
import java.io.IOException; import java.net.URI; import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; void main() throws IOException, InterruptedException { try (HttpClient client = HttpClient.newHttpClient()) { HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://httpbin.org/headers")) .header("X-Custom-Header", "MyCustomValue") .header("User-Agent", "Java HttpClient client") .GET() .build(); HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body()); } }
此示例向 https://httpbin.org/headers
发送一个带有自定义头部的 GET 请求。
.header("X-Custom-Header", "MyCustomValue")
我们添加一个名为 X-Custom-Header
并带有特定值的自定义头部。
.header("User-Agent", "Java HttpClient client")
我们用一个自定义值覆盖默认的 User-Agent
头部。
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body());
我们发送请求并打印响应,其中包含已发送的头部。
流式响应数据
此示例展示了如何将响应作为行流来处理。
import java.io.IOException; import java.net.URI; import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.util.stream.Stream; void main() throws IOException, InterruptedException { try (HttpClient client = HttpClient.newHttpClient()) { HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://httpbin.org/stream/5")) .GET() .build(); HttpResponse<Stream<String>> response = client.send(request, HttpResponse.BodyHandlers.ofLines()); response.body().forEach(line -> System.out.println("Line: " + line)); } }
此示例发送一个 GET 请求,并将响应作为行流进行处理。
HttpResponse<Stream<String>> response = client.send(request, HttpResponse.BodyHandlers.ofLines());
我们使用 BodyHandlers.ofLines
将响应作为字符串流来处理。
response.body().forEach(line -> System.out.println("Line: " + line));
我们遍历行流并打印每一行。
DELETE 请求
此示例演示如何发送 DELETE 请求以从服务器删除资源。
import java.io.IOException; import java.net.URI; import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; void main() throws IOException, InterruptedException { try (HttpClient client = HttpClient.newHttpClient()) { HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://httpbin.org/delete")) .method("DELETE", HttpRequest.BodyPublishers.noBody()) .build(); HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString()); System.out.println("Status Code: " + response.statusCode()); System.out.println("Response: " + response.body()); } }
此示例向 https://httpbin.org/delete
发送一个 DELETE 请求并打印响应。
HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://httpbin.org/delete")) .method("DELETE", HttpRequest.BodyPublishers.noBody()) .build();
我们使用 BodyPublishers.noBody
创建一个没有主体的 DELETE 请求。
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
我们发送请求并以字符串形式检索响应。
System.out.println("Status Code: " + response.statusCode()); System.out.println("Response: " + response.body());
我们打印状态码和响应主体以验证请求的结果。
HTTP 基本身份验证
此示例展示了如何在请求中包含 HTTP 基本身份验证。
import java.io.IOException; import java.net.URI; import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.util.Base64; void main() throws IOException, InterruptedException { String credentials = Base64.getEncoder().encodeToString("user:passwd".getBytes()); try (HttpClient client = HttpClient.newHttpClient()) { HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://httpbin.org/basic-auth/user/passwd")) .header("Authorization", "Basic " + credentials) .GET() .build(); HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString()); System.out.println("Status Code: " + response.statusCode()); System.out.println("Response: " + response.body()); } }
此示例向 https://httpbin.org/basic-auth/user/passwd
发送一个带有基本身份验证的 GET 请求。
String credentials = Base64.getEncoder().encodeToString("user:passwd".getBytes());
我们将用户名和密码编码为 Base64 格式以用于基本身份验证。
.header("Authorization", "Basic " + credentials)
我们添加带有编码凭据的 Authorization
头部。
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString()); System.out.println("Status Code: " + response.statusCode()); System.out.println("Response: " + response.body());
我们发送请求并打印状态码和响应主体。
并发请求
此示例演示如何使用 HttpClient 并发发送多个 HTTP 请求。
import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; void main() { try (HttpClient client = HttpClient.newHttpClient()) { List<HttpRequest> requests = List.of( HttpRequest.newBuilder().uri(URI.create("https://httpbin.org/get")).GET().build(), HttpRequest.newBuilder().uri(URI.create("https://webcode.me")).GET().build() ); List<CompletableFuture<HttpResponse<String>>> futures = requests.stream() .map(request -> client.sendAsync(request, HttpResponse.BodyHandlers.ofString())) .toList(); CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join(); for (CompletableFuture<HttpResponse<String>> future : futures) { HttpResponse<String> response = future.join(); System.out.println("Status: " + response.statusCode() + ", URI: " + response.uri()); } } }
此示例并发发送多个 GET 请求并处理它们的响应。
List<HttpRequest> requests = List.of( HttpRequest.newBuilder().uri(URI.create("https://httpbin.org/get")).GET().build(), HttpRequest.newBuilder().uri(URI.create("https://webcode.me")).GET().build() );
我们创建一个要并发发送的 HTTP 请求列表。
List<CompletableFuture<HttpResponse<String>>> futures = requests.stream() .map(request -> client.sendAsync(request, HttpResponse.BodyHandlers.ofString())) .toList();
我们使用 sendAsync
将每个请求映射到一个异步的 CompletableFuture
。
CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join(); for (CompletableFuture<HttpResponse<String>> future : futures) { HttpResponse<String> response = future.join(); System.out.println("Status: " + response.statusCode() + ", URI: " + response.uri()); }
我们等待所有请求完成,并打印它们的状态码和 URI。
来源
在本文中,我们利用 Java HttpClient 创建了 HTTP 请求。
作者
查看所有 Java 教程。