如何使用Java 11 HttpClient先仅发请求头校验响应后再发请求体
Java 11 HttpClient 先发送请求头校验再发送请求体实现方案
你现有代码默认使用GET请求,本身无请求体,如果你需要实现带请求体的请求先校验头再发体,可参考以下两种符合HTTP标准的实现方案:
方案1:使用Expect: 100-continue机制(推荐,仅一次请求)
这是HTTP协议原生支持的能力,完全匹配你的需求:
- 客户端发送请求头时携带
Expect: 100-continue标识 - 服务端校验请求头合法则返回
100 Continue响应,客户端收到后再发送请求体 - 服务端校验不通过直接返回4xx/5xx错误,客户端不会再发送请求体
实现步骤
- 开启HttpClient的100-continue支持,需在HttpClient实例化前设置系统参数:
System.setProperty("jdk.httpclient.expectContinue", "true");
也可以在JVM启动参数中添加-Djdk.httpclient.expectContinue=true实现全局配置。
- 构建请求时添加
Expect头并配置请求体:
HttpClient httpClient = HttpClient.newBuilder() .version(HttpClient.Version.HTTP_2) .followRedirects(HttpClient.Redirect.NORMAL) .connectTimeout(Duration.ofSeconds(10)) .authenticator(Authenticator.getDefault()) .build(); // 实际业务请求体 String requestBody = "{\"key\":\"value\"}"; HttpRequest httpRequest = HttpRequest.newBuilder(URI.create("someEndpoint")) .header(CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) .header(AUTHORIZATION, "someApiKey") // 添加Expect头触发100-continue流程 .header("Expect", "100-continue") // 配置请求方法和请求体 .POST(HttpRequest.BodyPublishers.ofString(requestBody)) .build(); HttpResponse<String> httpResponse = httpClient.send(httpRequest, HttpResponse.BodyHandlers.ofString());
注意:主流服务端框架(Nginx、Tomcat、Spring Boot等)默认都支持
100-continue机制,无需额外配置。
方案2:先发HEAD请求校验(兼容不支持100-continue的服务端)
如果服务端不支持100-continue机制,可以先发送HEAD请求校验请求头合法性,HEAD请求仅传输请求头和响应头,不会携带任何请求体/响应体,校验通过后再发送带业务请求体的实际请求。
实现代码
HttpClient httpClient = HttpClient.newBuilder() .version(HttpClient.Version.HTTP_2) .followRedirects(HttpClient.Redirect.NORMAL) .connectTimeout(Duration.ofSeconds(10)) .authenticator(Authenticator.getDefault()) .build(); // 第一步:发送HEAD请求校验请求头 HttpRequest headRequest = HttpRequest.newBuilder(URI.create("someEndpoint")) .method("HEAD", HttpRequest.BodyPublishers.noBody()) .header(CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) .header(AUTHORIZATION, "someApiKey") .build(); HttpResponse<Void> headResponse = httpClient.send(headRequest, HttpResponse.BodyHandlers.discarding()); // 自定义校验规则,示例为校验状态码为2xx if (headResponse.statusCode() < 200 || headResponse.statusCode() >= 300) { throw new RuntimeException("请求头校验失败,状态码:" + headResponse.statusCode()); } // 第二步:校验通过后发送带请求体的业务请求 String requestBody = "{\"key\":\"value\"}"; HttpRequest postRequest = HttpRequest.newBuilder(URI.create("someEndpoint")) .header(CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) .header(AUTHORIZATION, "someApiKey") .POST(HttpRequest.BodyPublishers.ofString(requestBody)) .build(); HttpResponse<String> postResponse = httpClient.send(postRequest, HttpResponse.BodyHandlers.ofString());
内容的提问来源于stack exchange,提问作者Dariusz Krynicki
相关产品推荐
相关产品推荐

