如何编写Java代码实现带指定请求头的curl等效POST请求
纯Java实现对应curl请求方案
不需要依赖第三方库、不需要调用shell脚本,使用Java原生API即可完整复现这条curl命令的所有逻辑,先明确curl参数和Java实现的对应关系:
-k:关闭HTTPS请求的SSL证书校验、跳过主机名校验--data-binary @/tmp/payload.json:读取本地/tmp/payload.json的原始字节内容作为POST请求体,不做任何转义-X POST:指定请求方法为POST- 所有
-H参数:逐个设置对应请求头 -v/-sS:可按需开启请求/响应日志打印,屏蔽无关输出
JDK 11+ 实现(无任何额外依赖)
JDK11开始内置的java.net.http.HttpClient可以非常简洁地实现需求,代码如下:
import java.net.URI; import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.nio.file.Files; import java.nio.file.Path; import java.security.SecureRandom; import java.security.cert.X509Certificate; import javax.net.ssl.SSLContext; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; import java.time.Duration; public class CurlClone { public static void main(String[] args) throws Exception { // 配置信任所有证书,对应curl的-k参数 TrustManager[] trustAllCerts = new TrustManager[]{ new X509TrustManager() { public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[0]; } public void checkClientTrusted(X509Certificate[] certs, String authType) {} public void checkServerTrusted(X509Certificate[] certs, String authType) {} } }; SSLContext sslContext = SSLContext.getInstance("TLS"); sslContext.init(null, trustAllCerts, new SecureRandom()); // 构建HttpClient,跳过主机名验证 HttpClient client = HttpClient.newBuilder() .sslContext(sslContext) .connectTimeout(Duration.ofSeconds(30)) .hostnameVerifier((hostname, session) -> true) .build(); // 读取payload.json的原始字节,对应--data-binary参数 byte[] payload = Files.readAllBytes(Path.of("/tmp/payload.json")); // 构建POST请求,设置所有请求头 HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://example.com/v2/search")) .timeout(Duration.ofSeconds(60)) .header("date", "Thu, 02 Jun 2022 04:44:19 GMT") .header("x-content-sha256", "xgxgfdgdfgJ/fgdfg+cvbcvbcvbvcbcv=") .header("content-type", "application/json") // content-length可手动指定,也可由HttpClient自动计算,自动计算更准确 .header("content-length", String.valueOf(payload.length)) .header("Authorization", "Signature version=\"1\",keyId=\"ocidx.tenancy.oc1..123455/ocidx.user.oc1..wergjkwerjkeg/12:df:fg:3b:0f:34:d1\",algorithm=\"rsa-sha256\",headers=\"(request-target) date host x-content-sha256 content-type content-length\",signature=\"sadfkjagsdkfjgkjsdgfkjgsdakjfgkjsadgfjkdgsjkgsdjkgfkjsdfkhkj/sdkfjgsdkjgfjksdfkjggkjgsdf+sdfhjvsjhdh+t2n3EdHZO5Qg5fxTm8F/ZhZJmWdeB+S+6H9T84r0tZNB5s0+sdkfjhsdkjfhjkdsgfjkdsjkfdjkgkjsdgjkgdk/hV5t4wTK/alsdkhsalkhd+wrq3Uw==\"") .POST(HttpRequest.BodyPublishers.ofByteArray(payload)) .build(); // 发送请求并获取响应 HttpResponse<byte[]> response = client.send(request, HttpResponse.BodyHandlers.ofByteArray()); // 打印响应信息,对应curl -v的输出效果 System.out.println("响应状态码:" + response.statusCode()); System.out.println("响应头:" + response.headers().map()); System.out.println("响应内容:" + new String(response.body())); } }
JDK8 版本实现说明
如果使用JDK8及更低版本,可使用自带的HttpsURLConnection实现,核心逻辑一致:
- 自定义
TrustManager和HostnameVerifier实现跳过SSL校验,对应-k参数 - 配置请求方法为POST,设置doOutput为true
- 逐个设置所有请求头
- 通过文件流读取
/tmp/payload.json的字节,写入请求输出流 - 读取响应输入流获取返回结果
注意事项
- 代码里的
date、x-content-sha256、Authorization头里的签名默认和给出的curl完全一致,如果这些值是动态生成的,替换成实际计算后的值即可 - 线上环境不建议长期开启
-k对应的跳过SSL校验逻辑,存在安全风险,仅建议调试时使用
内容的提问来源于stack exchange,提问作者LOrD_ARaGOrN
相关产品推荐
相关产品推荐

