在 Java 中发起 HTTP 代理请求不需要任何第三方库:JDK 自带的 HttpURLConnection 配合 java.net.Proxy 类,就能以连接为单位精确指定代理。除这种显式方式外,还可以通过系统属性做进程级全局代理,或用 ProxySelector 按目标地址动态选择节点。本文以 Proxy 类为主线讲解完整示例、认证与超时设置,并梳理各方案的适用边界。
环境准备与三种配置方式对比
JDK 8 及以上版本无需额外 jar 包,导入 java.net 包下的相关类即可开工。三种代理方式各有取舍,先做选型再动手:
- Proxy 参数:url.openConnection(proxy) 只影响这一个连接,粒度最细,推荐作为默认方案。
- 系统属性:设置 http.proxyHost 等属性后全局生效,适合一次性脚本或无法修改代码的场景。
- ProxySelector:按目标地址返回不同代理,适合代理池与多出口调度。
使用 Proxy 类建立代理连接
Proxy.Type.HTTP 表示普通正向代理,地址与端口由 InetSocketAddress 指定。拿到 HttpURLConnection 后,connectTimeout 控制与代理建立连接的最长时间,readTimeout 控制读取数据的等待上限,二者相互独立,单位都是毫秒。目标 URL 协议是 https 时会自动经代理走 CONNECT 隧道,无需开发者额外处理 TLS 层面的问题。
完整代码示例
下面的例子通过 Proxy 打开连接,设置了双阶段超时并正确读取响应:
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.Scanner;
public class ProxyDemo {
public static void main(String[] args) throws IOException {
Proxy proxy = new Proxy(
Proxy.Type.HTTP,
new InetSocketAddress("127.0.0.1", 8080));
URL url = new URL("https://httpbin.org/ip");
HttpURLConnection conn = (HttpURLConnection) url.openConnection(proxy);
conn.setConnectTimeout(10_000);
conn.setReadTimeout(15_000);
conn.setRequestProperty("User-Agent", "Mozilla/5.0");
int code = conn.getResponseCode();
System.out.println("状态码: " + code);
try (InputStream in = conn.getInputStream();
Scanner scanner = new Scanner(in, StandardCharsets.UTF_8)
.useDelimiter("\\A")) {
System.out.println(scanner.hasNext() ? scanner.next() : "");
} finally {
conn.disconnect();
}
}
}
代码用 try-with-resources 关闭输入流,并在 finally 中断开连接。需要特别注意:getInputStream 在收到 4xx、5xx 响应时会抛出 IOException,此时应改读 getErrorStream 获取错误响应体,这是 HttpURLConnection 一个非常容易踩坑的细节。
代理认证与系统属性方式
代理返回 407 时需要认证。JDK 的标准做法是调用 Authenticator.setDefault 注册全局认证器,在回调里返回 PasswordAuthentication 对象;也可以手动拼接 Proxy-Authorization 请求头,值为 Basic 加上 Base64 编码的「用户名:密码」。系统属性方式则更省事:System.setProperty("http.proxyHost", "127.0.0.1") 与 setProperty("http.proxyPort", "8080"),或在启动命令追加 -Dhttp.proxyHost=127.0.0.1 -Dhttp.proxyPort=8080。HTTPS 流量对应 https.proxyHost 属性,http.nonProxyHosts 可以配置不走代理的例外清单。
常见异常与注意事项
- ConnectException: Connection refused:代理地址或端口错误,先确认代理进程存活。
- SocketTimeoutException: connect timed out:与代理握手超时,可能是网络链路不通或代理过载。
- 407 与认证异常:账号密码错误,或代理要求先绑定出口 IP 白名单。
- 响应乱码:按响应头 Content-Type 显式指定字符集读取,不要依赖平台默认编码。
Article ID: 34
(本文仅供技术交流,请遵守法律法规)