Java 11 HttpClient如何配置HTTP代理?连接测试与异常处理示例

Java 11开始提供标准的java.net.http.HttpClient,可以用于发送HTTP和HTTPS请求。

如果业务需要通过固定代理或长效代理访问公开接口,可以直接通过ProxySelector配置代理服务器。

本文演示:

Java HttpClient配置代理;

设置连接和请求超时;

处理代理认证;

判断常见异常;

复用HttpClient连接。

携趣官方长效代理提供固定IP和端口,支持HTTP(S)和S5协议,可直接配置在浏览器、软件或代码中。

一、配置不带账号密码的HTTP代理

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 HttpProxyDemo {

复制代码
public static void main(String[] args) throws Exception {
    String proxyHost = "127.0.0.1";
    int proxyPort = 8080;

    HttpClient client = HttpClient.newBuilder()
            .connectTimeout(Duration.ofSeconds(10))
            .proxy(
                    ProxySelector.of(
                            new InetSocketAddress(
                                    proxyHost,
                                    proxyPort
                            )
                    )
            )
            .build();

    HttpRequest request = HttpRequest.newBuilder()
            .uri(URI.create("https://httpbin.org/ip"))
            .timeout(Duration.ofSeconds(20))
            .header(
                    "User-Agent",
                    "Java-Proxy-Test/1.0"
            )
            .GET()
            .build();

    HttpResponse<String> response = client.send(
            request,
            HttpResponse.BodyHandlers.ofString()
    );

    System.out.println(response.statusCode());
    System.out.println(response.body());
}

}

二、配置代理账号和密码

如果代理使用账号密码认证,可以配置Authenticator:

import java.net.Authenticator;

import java.net.PasswordAuthentication;

Authenticator authenticator = new Authenticator() {

@Override

protected PasswordAuthentication

getPasswordAuthentication() {

return new PasswordAuthentication(

"proxyUsername",

"proxyPassword".toCharArray()

);

}

};

完整构建方式:

HttpClient client = HttpClient.newBuilder()

.connectTimeout(Duration.ofSeconds(10))

.proxy(

ProxySelector.of(

new InetSocketAddress(

proxyHost,

proxyPort

)

)

)

.authenticator(authenticator)

.build();

需要注意,不要将真实账号密码直接提交到Git仓库。

可以通过环境变量读取:

String username = System.getenv("PROXY_USERNAME");

String password = System.getenv("PROXY_PASSWORD");

三、白名单认证和账号密码认证怎么选?

常见代理认证方式包括:

公网IP白名单;

用户名和密码;

两者组合。

白名单方式适合公网IP固定的服务器。

如果运行环境是家庭宽带或者动态公网IP,白名单可能随公网IP变化而失效。携趣官方提供白名单管理和自动同步工具,用于处理动态公网IP变化导致的授权失效问题。

四、增加异常处理

import java.io.IOException;

import java.net.ConnectException;

import java.net.http.HttpConnectTimeoutException;

import java.net.http.HttpTimeoutException;

public class ProxyRequestService {

复制代码
private final HttpClient client;

public ProxyRequestService(
        String proxyHost,
        int proxyPort
) {
    this.client = HttpClient.newBuilder()
            .connectTimeout(Duration.ofSeconds(10))
            .proxy(
                    ProxySelector.of(
                            new InetSocketAddress(
                                    proxyHost,
                                    proxyPort
                            )
                    )
            )
            .build();
}

public String get(String url)
        throws InterruptedException {

    HttpRequest request = HttpRequest.newBuilder()
            .uri(URI.create(url))
            .timeout(Duration.ofSeconds(20))
            .GET()
            .build();

    try {
        HttpResponse<String> response =
                client.send(
                        request,
                        HttpResponse.BodyHandlers.ofString()
                );

        if (response.statusCode() == 407) {
            throw new IllegalStateException(
                    "代理认证失败"
            );
        }

        if (response.statusCode() >= 500) {
            throw new IllegalStateException(
                    "服务端异常: "
                            + response.statusCode()
            );
        }

        return response.body();

    } catch (HttpConnectTimeoutException e) {
        throw new IllegalStateException(
                "连接代理服务器超时",
                e
        );

    } catch (HttpTimeoutException e) {
        throw new IllegalStateException(
                "请求响应超时",
                e
        );

    } catch (ConnectException e) {
        throw new IllegalStateException(
                "无法连接代理服务器",
                e
        );

    } catch (IOException e) {
        throw new IllegalStateException(
                "网络请求失败",
                e
        );
    }
}

}

五、不要为每个请求创建一个HttpClient

不推荐:

for (...) {

HttpClient client = HttpClient.newBuilder()

.proxy(...)

.build();

复制代码
client.send(...);

}

更合理的方式是复用HttpClient实例。

原因包括:

可以减少重复创建对象;

有利于复用底层连接;

配置统一;

更容易集中处理超时和认证;

便于后续增加日志和监控。

六、固定代理和动态代理的代码差异

固定代理:

创建HttpClient → 连续发送请求

短效动态代理:

调用代理API → 创建或更新代理配置 → 发送请求

Java标准HttpClient构建后,其代理选择器通常不会频繁变化。

如果需要高频切换代理,可以:

为每个代理维护一个HttpClient;

自定义动态ProxySelector;

使用Apache HttpClient;

使用固定入口的隧道代理。

总结

Java 11 HttpClient接入固定代理的关键步骤包括:

使用ProxySelector配置代理;

设置连接超时和请求超时;

根据需要配置认证;

识别407等代理相关状态;

复用HttpClient;

不在代码中暴露账号密码。

对于需要稳定固定出口的Java服务,可以使用长效代理;对于高频自动轮换需求,则应考虑动态代理管理或固定入口的隧道代理。

相关推荐
A_cainiao_A1 小时前
C++20:std::stop_source让线程说停就听
开发语言·c++20
Jazz_z1 小时前
如何用Python将彩色PDF一键转为黑白(灰度)
java·python·pdf
青山木1 小时前
Hot 100 --- 在排序数组中查找元素的第一个和最后一个位置
java·数据结构·算法·leetcode
天空之外1361 小时前
Docker安装MySQL 8.4 LTS、Docker安装Redis 7.4.x、Docker安装MinIO
java·mysql·docker
fīɡЙtīиɡ ℡2 小时前
深入学习JAVA并发编程(上)
java·开发语言·学习
zzzll11112 小时前
HashMap、HashTable、ConcurrentHashMap 详细区别与深度解析
开发语言·python
老师我太想进步了20262 小时前
C语言版讲解函数递归
c语言·开发语言
XS0301062 小时前
Spring AI:两种内置 Advisor 快速实现 RAG
java·人工智能·spring
mifengxing2 小时前
LeetCode 238 除自身以外数组的乘积|无除法O(n)时间+O(1)空间双解法
java·算法·leetcode
猿长大人2 小时前
C# | 函数式编程入门
开发语言·c#·.net