通过Java中的代理服务器进行连接

2023/06/01

1. 概述

代理服务器充当客户端应用程序和其他服务器之间的中介。在企业环境中,我们经常使用它们来帮助控制用户通常跨越网络边界消费的内容。

在本教程中,我们将了解如何通过Java中的代理服务器进行连接

首先,我们将探索更老的、更全局的方法,它在JVM范围内使用系统属性进行配置。之后,我们将介绍Proxy类,它通过允许在每个连接的基础上进行配置来为我们提供更多控制。

2. 设置

要运行本文中的示例,我们需要访问代理服务器。Squid是一种流行的实现,可用于大多数操作系统。Squid的默认配置对于我们的大多数示例来说已经足够好了。

3. 使用全局设置

Java公开了一组系统属性,可用于配置JVM范围内的行为。如果适用于用例,这种“一刀切”的方法通常最容易实现。

我们可以在调用JVM时从命令行设置所需的属性。作为替代方案,我们也可以通过在运行时调用System.setProperty()来设置它们

3.1 可用的系统属性

Java为HTTP、HTTPS、FTP和SOCKS协议提供了代理处理程序。可以为每个处理程序定义一个代理作为主机名和端口号:

  • http.proxyHost:HTTP代理服务器的主机名
  • http.proxyPort:HTTP代理服务器的端口号–属性是可选的,如果未提供则默认为80
  • http.nonProxyHosts:应该绕过代理的主机模式的竖线分隔(“ ”)列表–如果设置则适用于HTTP和HTTPS处理程序
  • socksProxyHost:SOCKS代理服务器的主机名
  • socksProxyPort:SOCKS代理服务器的端口号
如果指定nonProxyHosts,主机模式可以以通配符(“*”)开头或结尾。可能需要转义Windows平台上的“ ”分隔符。可以在Oracle关于网络属性的官方Java文档中找到所有可用的代理相关系统属性的详尽列表。

3.2 通过命令行参数设置

我们可以通过将设置作为系统属性传递来在命令行上定义代理:

java -Dhttp.proxyHost=127.0.0.1 -Dhttp.proxyPort=3128 proxies.networking.cn.tuyucheng.taketoday.CommandLineProxyDemo

当以这种方式启动一个进程时,我们可以简单地在URL上使用openConnection()而无需任何额外的工作:

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

3.3 使用System.setProperty(String, String)设置

如果我们无法在命令行上设置代理属性,我们可以在我们的程序中调用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();
// ...

如果我们稍后手动取消设置相关的系统属性,那么将不再使用代理:

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

3.4 全局配置的限制

尽管使用具有系统属性的全局配置很容易实现,但这种方法限制了我们可以做的事情,因为设置适用于整个JVM。出于这个原因,为特定协议定义的设置在JVM的生命周期内是有效的,或者直到它们被取消设置。

要绕过此限制,可能很想根据需要打开和关闭设置。为了在多线程程序中安全地执行此操作,有必要采取措施来防止并发问题。

作为替代方案,Proxy API提供了对代理配置的更精细控制

4. 使用Proxy API

Proxy类为我们提供了一种在每个连接的基础上配置代理的灵活方法。如果存在任何现有的JVM范围的代理设置,使用Proxy类的基于连接的代理设置将覆盖它们。

我们可以通过Proxy.Type定义三种类型的代理:

  • HTTP:使用HTTP协议的代理
  • SOCKS:使用SOCKS协议的代理
  • DIRECT:没有代理的明确配置的直接连接

4.1 使用HTTP代理

要使用HTTP代理,我们首先使用Proxy和Proxy.Type.HTTP类型包装一个SocketAddress实例。接下来,我们只需将Proxy实例传递给URLConnection.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);

简而言之,这意味着我们将连接到URL_STRING,然后通过托管在127.0.0.1:3128的代理服务器路由该连接。

4.2 使用直接代理

我们可能需要直接连接到主机。在这种情况下,我们可以使用静态Proxy.NO_PROXY实例显式绕过可能在全局配置的代理。在幕后,API为我们构造了一个新的Proxy实例,使用Proxy.Type.DIRECT作为类型:

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

基本上,如果没有全局配置的代理,那么这与不带参数调用openConnection()是一样的。

4.3 使用SOCKS代理

使用URLConnection时,使用SOCKS代理类似于HTTP变体。我们首先使用Proxy.Type.SOCKS类型用Proxy包装SocketAddress实例。之后,我们将Proxy实例传递给URLConnection.openConnection:

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

连接到TCP套接字时也可以使用SOCKS代理。首先,我们使用Proxy实例构造一个Socket。之后,我们将目标SocketAddress实例传递给Socket.connect()

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

5. 总结

在本文中,我们研究了如何在核心Java中使用代理服务器。

首先,我们研究了使用系统属性通过代理服务器进行连接的更旧的、更全局的连接方式。然后,我们看到了如何使用Proxy类,它在通过代理服务器连接时提供细粒度的控制。

与往常一样,本教程的完整源代码可在GitHub上获得。

Show Disqus Comments

Post Directory

扫码关注公众号:Taketoday
发送 290992
即可立即永久解锁本站全部文章