Java 11 及以上版本可在客户端构建器上设置 ProxySelector。这样无需改动整个 JVM 的代理属性:

import java.net.InetSocketAddress;
import java.net.ProxySelector;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Duration;

public class ProxyExample {
    public static void main(String[] args) throws Exception {
        HttpClient client = HttpClient.newBuilder()
            .proxy(ProxySelector.of(
                new InetSocketAddress("203.0.113.10", 8080)))
            .connectTimeout(Duration.ofSeconds(5))
            .build();

        HttpRequest request = HttpRequest.newBuilder()
            .uri(URI.create("https://example.com/"))
            .timeout(Duration.ofSeconds(15))
            .GET()
            .build();

        HttpResponse<String> response = client.send(
            request, HttpResponse.BodyHandlers.ofString());
        System.out.println(response.statusCode());
        System.out.println(response.body());
    }
}

将文档示例端点换成自己的 HTTP 代理;HTTP 代理列表提供可供测试的候选。ProxySelector.of 接收套接字地址:主机部分不要带 http:// 前缀,并单独传入端口。它选择的是 HTTP 代理,不会根据端口号变成 SOCKS。请求 URI 仍是实际目标。

HTTPS 可以通过隧道经过这个 HTTP 代理。无需将目标降级,而且这项配置也不代表代理监听端本身支持 TLS。

客户端构建器上的连接超时在建立连接时生效,请求另有自己的超时。两者都应明确保留,因为请求可能复用现有连接。网络、认证或隧道异常可能在任何目标响应之前发生,而收到错误状态并不一定抛出异常。

相同路由策略的请求应复用客户端,让应用利用其连接管理能力。

相关文章