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 项目 中找到。