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

评论 0 浏览 0 2018-12-10

一、简介

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

在本教程中,我们将了解如何通过 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 com.baeldung.networking.proxies.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 的生命周期内都处于活动状态,或者直到它们被取消设置为止。

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

作为替代方案,代理 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 代理

使用 SOCKS 代理与使用 URLConnection 时的 HTTP 变体类似。我们首先使用代理包装 SocketAddress 实例Proxy.Type.SOCKS 的类型。然后,我们将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 上找到。

最后更新2023-09-09
0 个评论
标签