java11 httpclient使用

一,基本用法

<pre><code class="language-java">
HttpClient client = HttpClient.newBuilder()
        //.sslContext(sslContext)
        .build();
HttpRequest request = HttpRequest.newBuilder()
        .uri(URI.create("https://gitlab.office.com"))
        .build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println("Response Body: " + response.body());
</code></pre>

二,进阶配置

1:创建httpclient,sslContext证书需要创建一个受信任的证书管理器


HttpClient client = HttpClient.newBuilder()
      .version(Version.HTTP_1_1)
      .proxy(ProxySelector.of(new InetSocketAddress("127.0.0.1", 8080)))
      .authenticator(Authenticator.getDefault())
      .sslContext(sslContext)
      .build();

2:创建httprequest


HttpRequest request = HttpRequest.newBuilder()
      .uri(URI.create("http://openjdk.java.net/"))
      .timeout(Duration.ofMinutes(1))
      .header("Content-Type", "application/json")
      .POST(BodyPublisher.fromFile(Paths.get("file.json")))
      //.POST(HttpRequest.BodyPublishers.ofString(JSON.toJSONString(notify)))
      .build()

3:发送请求


// 同步
HttpResponse response =
      client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.statusCode());
System.out.println(response.body());

// 异步
client.sendAsync(request, HttpResponse.BodyHandlers.ofString())
      .thenApply(response -> { System.out.println(response.statusCode());
                               return response; } )
      .thenApply(HttpResponse::body)
      .thenAccept(System.out::println);

4:创建受信任的证书管理器


public static SSLContext sslContext() throws Exception {
    TrustManager[] trustAllCerts = new TrustManager[]{
            new X509TrustManager() {
                public void checkClientTrusted(X509Certificate[] chain, String authType) {}
                public void checkServerTrusted(X509Certificate[] chain, String authType) {}
                public X509Certificate[] getAcceptedIssuers() {
                    return new X509Certificate[0];
                }
            }
    };
    SSLContext sslContext = SSLContext.getInstance("TLS");
    sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
    return sslContext;
}

作用:

  • 创建了一个 TrustManager 数组,其中的元素是一个自定义的 X509TrustManager
  • X509TrustManager 是处理 X.509 证书的信任管理器,用于检查客户端和服务器端的证书。

方法说明:

checkClientTrusted(X509Certificate[] chain, String authType)

    • 用于验证客户端证书。
    • 此处没有实际验证逻辑,直接跳过(空实现)。

checkServerTrusted(X509Certificate[] chain, String authType)

    • 用于验证服务器端证书。
    • 同样没有验证逻辑,直接跳过。

getAcceptedIssuers()

    • 返回受信任的证书颁发机构列表。
    • 此处返回一个空数组,意味着它不会对任何证书进行验证。

5:自签名的输入导入信任库之后,httpclient会自动识别


keytool -import -trustcacerts -keystore $JAVA_HOME/lib/security/cacerts -storepass changeit -alias mycert -file mycert.crt

6:自定义证书验证逻辑

如果需要加载特定的信任库(比如企业内部的 CA),可以使用自定义的 SSLContext


import java.io.FileInputStream;
import java.net.URI;
import java.net.http.*;
import java.security.KeyStore;
import javax.net.ssl.*;

public class CustomCertificateExample {
    public static void main(String[] args) throws Exception {
        // 加载自定义的信任库
        KeyStore trustStore = KeyStore.getInstance("JKS");
        try (FileInputStream trustStoreStream = new FileInputStream("my-truststore.jks")) {
            trustStore.load(trustStoreStream, "password".toCharArray());
        }

        // 创建 TrustManagerFactory 并初始化
        TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
        trustManagerFactory.init(trustStore);

        // 配置 SSLContext
        SSLContext sslContext = SSLContext.getInstance("TLS");
        sslContext.init(null, trustManagerFactory.getTrustManagers(), new java.security.SecureRandom());

        // 配置 HttpClient
        HttpClient client = HttpClient.newBuilder()
            .sslContext(sslContext)
            .build();

        // 发送请求
        HttpRequest request = HttpRequest.newBuilder()
            .uri(new URI("https://example.com"))
            .GET()
            .build();

        HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString());
        System.out.println("Response Code: " + response.statusCode());
        System.out.println("Response Body: " + response.body());
    }
}

7:验证自定义逻辑

如果需要自定义校验逻辑,比如验证证书的某些额外信息,可以扩展 X509TrustManager


TrustManager[] customTrustManagers = new TrustManager[]{
    new X509TrustManager() {
        public void checkClientTrusted(X509Certificate[] chain, String authType) {
            // 可选:校验客户端证书
        }

        public void checkServerTrusted(X509Certificate[] chain, String authType) {
            for (X509Certificate cert : chain) {
                System.out.println("Certificate Subject: " + cert.getSubjectDN());
                // 进行额外的验证逻辑,例如:
                // - 检查证书的颁发机构
                // - 检查证书的扩展字段
                // - 验证域名
            }
        }

        public X509Certificate[] getAcceptedIssuers() {
            return new X509Certificate[0];
        }
    }
};

8:下载文件示例


public static void downloadByTag(String tagId) throws Exception {
    SSLContext sslContext = sslContext();
    HttpClient client = HttpClient.newBuilder()
            .sslContext(sslContext)
            .build();
    String fileUrl = "https://gitlab.office.iauto.com/idesigner/piu_cm/-/raw/"+tagId+"/ECUProject_Mst.arxml?inline=false";
    String outputFilePath = "1.arxml";
    HttpRequest request = HttpRequest.newBuilder()
            .uri(URI.create(fileUrl))
            .GET()
            .build();
    HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofInputStream());
    if (response.statusCode() == 200) {
        try (InputStream inputStream = response.body();
             FileOutputStream outputStream = new FileOutputStream(outputFilePath)) {
            byte[] buffer = new byte[2048];
            int bytesRead;
            while ((bytesRead = inputStream.read(buffer)) != -1) {
                outputStream.write(buffer, 0, bytesRead);
            }
            System.out.println("文件下载成功: " + outputFilePath);
        }
    } else {
        System.out.println("下载失败,状态码: " + response.statusCode());
    }
}