package space.anyi.httpClient; import java.io.IOException; import java.net.URI; import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpRequest.BodyPublishers; import java.net.http.HttpResponse; import java.net.http.HttpResponse.BodyHandlers; import java.time.Duration; /** * HTTP Request 配置项示例 * *
HttpRequest 本身可通过 Builder 配置的项(区别于 HttpClient 级配置):
*典型用途:提交大请求体前先「询价」,服务器返回 100 后再真正发送请求体, * 避免无谓地传输大文件。
*/ public HttpRequest buildWithExpectContinue() { return HttpRequest.newBuilder() .uri(URI.create(BASE_URL + "/api/users")) .header("Content-Type", "application/json") // 声明期望服务器先返回 100-continue .expectContinue(true) .POST(BodyPublishers.ofString("{\"name\":\"x\",\"account\":\"y\",\"sex\":\"z\"}")) .build(); } /** * 自定义请求方法:method(name, bodyPublisher)。 * *GET/POST/PUT/DELETE 之外的任意方法(如 PATCH、HEAD)都用这个入口。 * 无请求体的方法传 BodyPublishers.noBody()。
*/ public HttpRequest buildWithCustomMethod() { return HttpRequest.newBuilder() .uri(URI.create(BASE_URL + "/api/users")) // 自定义 PATCH 方法,无请求体 .method("PATCH", BodyPublishers.noBody()) .build(); } /** * 复制 Builder:copy() 返回独立的副本,之后修改副本不影响原 Builder。 * *JDK 的 copy() 采用「写时复制」:复制后两者的配置相互独立, * 后续对任一方的修改都不会影响另一方。
*/ public CopyPair buildWithCopy() { // 原 Builder:只带 X-Original 头 HttpRequest.Builder original = HttpRequest.newBuilder() .uri(URI.create(BASE_URL + "/api/users")) .header("X-Original", "yes"); // 复制并修改副本:加上 X-Copy 头(使用不同 header 名便于验证独立性) HttpRequest copied = original.copy() .header("X-Copy", "yes") .GET() .build(); // 修改副本后,原 Builder 依旧只含 X-Original HttpRequest originalBuilt = original.GET().build(); return new CopyPair(originalBuilt, copied); } /** * 携带「复制前的原请求」与「复制后修改的副本请求」的成对结果。 */ public record CopyPair(HttpRequest original, HttpRequest copied) { } /** * 使用带超时的请求发送 GET,验证请求级配置不影响请求执行。 */ public HttpResponse