在 Java HttpClient 中使用 HTTP 代理
向 Java HTTP 客户端构建器传入 ProxySelector,并将连接超时与请求超时分开设置。
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。
客户端构建器上的连接超时在建立连接时生效,请求另有自己的超时。两者都应明确保留,因为请求可能复用现有连接。网络、认证或隧道异常可能在任何目标响应之前发生,而收到错误状态并不一定抛出异常。
相同路由策略的请求应复用客户端,让应用利用其连接管理能力。