1. 简介

代理服务器(Proxy Server)在客户端应用和目标服务器之间起到中介作用。在企业环境中,我们经常使用代理来控制用户访问的内容,尤其是在跨越网络边界时。

本文将重点介绍 如何在 Java 核心 API 中配置并使用代理服务器进行网络连接

首先会介绍一种全局配置的方式,这种方式作用于整个 JVM,通过系统属性进行设置;随后会介绍使用 Proxy 类的方法,这种方式更加灵活,支持按连接粒度进行配置。

2. 环境准备

为了运行本文中的示例代码,你需要一个可用的代理服务器。推荐使用 Squid,它是一个跨平台的开源代理服务器,默认配置即可满足大多数场景需求。

3. 使用全局配置方式

Java 提供了一组系统属性(System Properties),可用于配置 JVM 范围内的代理行为。如果场景允许,这种方式是最简单粗暴的。

你可以 在启动 JVM 时通过命令行参数设置这些属性,也可以在运行时通过调用 System.setProperty() 方法来动态设置。

3.1. 可用的系统属性

Java 为 HTTP、HTTPS、FTP 和 SOCKS 协议提供了代理支持。每个协议都可以通过指定主机名和端口号来配置代理:

  • http.proxyHost – HTTP 代理服务器的主机名
  • http.proxyPort – HTTP 代理服务器的端口号,默认为 80
  • http.nonProxyHosts – 不使用代理的主机列表,以“|”分隔,支持通配符(如 *.local
  • socksProxyHost – SOCKS 代理服务器的主机名
  • socksProxyPort – SOCKS 代理服务器的端口号,默认为 1080

⚠️ 注意:nonProxyHosts 对 HTTP 和 HTTPS 都生效。在 Windows 平台上可能需要对 | 字符进行转义。

完整属性列表可参考 Oracle 官方文档:Networking Properties

3.2. 通过命令行参数设置

你可以在启动 JVM 时通过命令行指定代理配置:

java -Dhttp.proxyHost=127.0.0.1 -Dhttp.proxyPort=3128 com.baeldung.networking.proxies.CommandLineProxyDemo

这样,在代码中就可以直接调用 openConnection() 方法,无需额外配置:

URL url = new URL(RESOURCE_URL);
URLConnection con = url.openConnection();

3.3. 使用 System.setProperty() 设置

如果无法通过命令行设置系统属性,可以在程序中使用 System.setProperty() 方法动态设置:

System.setProperty("http.proxyHost", "127.0.0.1");
System.setProperty("http.proxyPort", "3128");

URL url = new URL(RESOURCE_URL);
URLConnection con = url.openConnection();
// ...

如果你之后手动将属性设为 null,则代理配置会被取消:

System.setProperty("http.proxyHost", null);

3.4. 全局配置的局限性

虽然使用系统属性配置代理非常方便,但它的局限性也很明显:配置作用于整个 JVM,无法灵活控制每个连接行为

如果想在运行时动态切换代理配置,尤其是在多线程环境中,需要引入额外的并发控制机制来避免冲突。

✅ 更推荐的做法是使用 Proxy API,它支持更细粒度的控制。

4. 使用 Proxy API

Java 提供了 Proxy 类,用于按连接粒度灵活配置代理。如果同时设置了全局代理和连接级代理,后者会覆盖前者。

Proxy.Type 支持以下三种类型:

  • HTTP – 使用 HTTP 协议的代理
  • SOCKS – 使用 SOCKS 协议的代理
  • DIRECT – 显式指定不使用代理,直接连接

4.1. 使用 HTTP 代理

使用 HTTP 代理时,先创建一个 Proxy 实例,类型为 Proxy.Type.HTTP,然后传入 openConnection() 方法:

URL weburl = new URL(URL_STRING);
Proxy webProxy 
  = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("127.0.0.1", 3128));
HttpURLConnection webProxyConnection 
  = (HttpURLConnection) weburl.openConnection(webProxy);

这段代码表示:通过 127.0.0.1:3128 的 HTTP 代理访问 URL_STRING

4.2. 使用 DIRECT 代理

如果你需要绕过全局代理配置,直接连接目标主机,可以使用静态实例 Proxy.NO_PROXY

HttpURLConnection directConnection 
  = (HttpURLConnection) weburl.openConnection(Proxy.NO_PROXY);

这相当于显式指定不使用代理,等价于没有全局代理时的 openConnection() 行为。

4.3. 使用 SOCKS 代理

使用 SOCKS 代理与 HTTP 类似,只需将类型改为 Proxy.Type.SOCKS

Proxy socksProxy 
  = new Proxy(Proxy.Type.SOCKS, new InetSocketAddress("127.0.0.1", 1080));
HttpURLConnection socksConnection 
  = (HttpURLConnection) weburl.openConnection(socksProxy);

✅ 此外,SOCKS 代理也可以用于 TCP Socket 连接:

Socket proxySocket = new Socket(socksProxy);
InetSocketAddress socketHost 
  = new InetSocketAddress(SOCKET_SERVER_HOST, SOCKET_SERVER_PORT);
proxySocket.connect(socketHost);

5. 总结

本文介绍了在 Java 中使用代理服务器的两种主要方式:

  • 使用系统属性进行全局配置,适合简单场景
  • 使用 Proxy 类进行连接级配置,适合复杂或动态代理需求

两种方式各有优劣,具体选择应根据实际业务场景决定。

✅ 所有示例代码均可在 GitHub 项目 中找到。


原始标题:Connecting through Proxy Servers in Core Java