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服务,可以使用长效代理;对于高频自动轮换需求,则应考虑动态代理管理或固定入口的隧道代理。

相关推荐
daidaidaiyu8 小时前
ThingsBoard 集群的核心逻辑源码分析
java
To_OC9 小时前
从一头雾水到跑通全流程:我用一个周末啃透了JWT登录鉴权
前端·后端·http
2601_962885729 小时前
如何用 Python 自动识别股票的支撑位与压力位?
开发语言·python
爱吃奥利奥_wen9 小时前
面向对象三板斧:封装、继承、多态,到底在“装“什么、“承“什么、“变“什么?
开发语言·经验分享·c#
我可能是个假开发9 小时前
FTP Unicode 文件名导致 `550` 的问题分析与解决方案
java·开发语言·spring
caoerzhong9 小时前
中小企业上 WMS 该先上哪几块:JeeWMS 开源 Java 仓库管理系统的分批上线清单
java·python·开源
WL学习笔记10 小时前
日期类(C++)
开发语言·c++·日期类实现
【JAVA】玩家10 小时前
Spring核心原理全解析:从零到生产实战
java·后端·spring
Wang's Blog11 小时前
Java框架 SpringCloud 快速入门: 实现 Feign 最佳实践(抽取方式)
java·spring cloud
谢亮_vipxieliang11 小时前
Go map与结构体的正确使用
开发语言·golang·哈希算法