代理配置

本页讨论命令行 Apache Ant 上的代理问题。有关代理设置的 IDE 特定信息,请参阅您的 IDE 文档。

在 Ant 的 JVM 中运行的所有任务和线程共享相同的 HTTP/FTP/Socks 代理配置。

当任何任务尝试从 HTTP 页面检索内容时,包括 <get> 任务、XML/XSL 任务中的任何自动 URL 检索,或使用 java.net.URL 类别的任何第三方任务,代理设置可能会决定成功或失败。

任何在阻止防火墙后面编写构建文件的人都会立即意识到这些问题,并可能希望编写一个构建文件来解决这个问题,但第三方构建文件的用户可能会发现构建文件本身在防火墙后面无法工作。

这是 Java 和 Ant 的一个长期存在的问题。解决它的唯一方法是使用代理设置显式配置 Ant,方法是将代理详细信息作为 JVM 属性传递,或者在 Java 5+ 系统上告诉 Ant 让 JVM 自己解决。

Java 5+ 代理支持

自 Ant 1.7 起

当 Ant 启动时,如果提供了 -autoproxy 命令,Ant 会设置 java.net.useSystemProxies 系统属性。这告诉 Java 5+ 运行时使用主机环境的当前属性设置集。其他 JVM,例如 Kaffe 和 Apache Harmony,将来也可能使用此属性。它在 Java 1.4 及更早版本的运行时中被忽略。

此属性可能足以让命令行 Ant 构建获得网络访问权限,尽管在实践中结果不一致。

据报道,它还破坏了 AIX 上的 IBM Java 5 运行时,并且并不总是适用于 Linux(可能是由于缺少 gconf 设置)。其他奇怪的事情也会出错,例如 Oracle JDBC 驱动程序或纯 Java SVN 客户端。

要使 -autoproxy 选项成为默认选项,请将其添加到环境变量 ANT_ARGS 中,该变量包含在每次命令行运行时传递给 Ant 的参数列表。

自动代理的工作原理

java.net.useSystemProxies 只在启动时检查一次,其他检查(注册表、gconf、系统属性)在需要时动态执行(套接字连接、URL 连接等)。

Windows

JVM 直接转到注册表,绕过 WinInet,因为它不存在/不一致于所有受支持的 Windows 平台(它实际上是 IE 的一部分)。Java 7 可能会在平台上使用 Windows API,当它存在时。

Linux

JVM 使用 gconf 库来查看特定条目。使用的 GConf-2 设置是

 - /system/http_proxy/use_http_proxy            boolean
 - /system/http_proxy/use_authentication        boolean
 - /system/http_proxy/host                      string
 - /system/http_proxy/authentication_user       string
 - /system/http_proxy/authentication_password   string
 - /system/http_proxy/port                      int
 - /system/proxy/socks_host                     string
 - /system/proxy/mode                           string
 - /system/proxy/ftp_host                       string
 - /system/proxy/secure_host                    string
 - /system/proxy/socks_port                     int
 - /system/proxy/ftp_port                       int
 - /system/proxy/secure_port                    int
 - /system/proxy/no_proxy_for                   list
 - /system/proxy/gopher_host                    string
 - /system/proxy/gopher_port                    int

如果您使用的是 KDE 或 Gnome 以外的其他 GUI,您仍然可以使用 gconf-editor 工具添加这些条目。

手动 JVM 选项

任何 JVM 都可以通过将适当的 -D 系统属性选项传递给运行时来显式配置其代理选项。Ant 可以通过所有 shell 脚本通过 ANT_OPTS 环境变量进行配置,该变量是提供给 Ant 的 JVM 的选项列表

对于 bash

export ANT_OPTS="-Dhttp.proxyHost=proxy -Dhttp.proxyPort=8080"

对于 csh/tcsh

setenv ANT_OPTS "-Dhttp.proxyHost=proxy -Dhttp.proxyPort=8080"

如果您将此行插入 Ant shell 脚本本身,它将被系统上通过命令行调用 Ant 的所有持续集成工具拾取。

对于 Windows,在相应的“我的电脑”属性对话框(XP),“计算机”属性(Vista)中设置 ANT_OPTS 环境变量

此机制跨 Java 版本有效,跨平台且可靠。设置后,所有通过命令行运行的构建文件将自动正确设置其代理,无需任何构建文件更改。它显然还覆盖了 Ant 的自动代理设置选项。

它在以下方面受到限制

  1. 在 IDE 中不起作用。这些需要更改其自己的代理设置
  2. 不够动态,无法处理笔记本电脑配置更改。

SetProxy 任务

可以使用 setproxy 任务 在构建文件中显式设置代理。这会操作 JVM 的许多代理配置属性,并从那时起控制同一 JVM 中所有网络操作的代理设置。

如果您有一个仅在内部使用、在防火墙后面、在旧版 JVM 上使用的构建文件,并且您无法更改 Ant 的 JVM 代理设置,那么这是您的最佳选择。它很丑陋且脆弱,因为构建文件现在包含系统配置信息。也很难在不同用户的许多可能的代理选项(无、HTTP、SOCKS)之间正确设置它。

请注意,使用此任务设置的代理配置可能会覆盖任何其他机制设置的代理配置。它还可以与巧妙的技巧一起使用,仅在代理被认为可达时才设置代理

<target name="probe-proxy" depends="init">
  <condition property="proxy.enabled">
    <and>
      <isset property="proxy.host"/>
      <isreachable host="${proxy.host}"/>
    </and>
  </condition>
</target>

<target name="proxy" depends="probe-proxy" if="proxy.enabled">
  <property name="proxy.port" value="80"/>
  <property name="proxy.user" value=""/>
  <property name="proxy.pass" value=""/>
  <setproxy proxyhost="${proxy.host}" proxyport="${proxy.port}"
            proxyuser="${proxy.user}" proxypassword="${proxy.pass}"/>
</target>

自定义 ProxySelector 实现

由于 Java 允许开发人员编写自己的 ProxySelector 实现,因此理论上可以有人编写自己的代理选择器类,该类使用不同的策略来确定代理设置。Ant 中没有对此的显式支持,据团队所知,还没有尝试过。

这可能是最灵活的解决方案,因为可以很容易地想象一个 Ant 特定的代理选择器,它由 ant 属性而不是系统属性驱动。开发人员可以在其自定义 build.properties 文件中设置代理选项,并使其传播。

这里的一个问题是并发性:默认代理选择器是每个 JVM,而不是每个线程,因此代理设置将应用于所有线程上打开的所有套接字;我们还面临着如何将选项从一个构建传播到 JVM 范围的选择器的问题。

配置 Ant 下 Java 程序的代理设置

任何使用 <java> 执行且未设置 fork=true 的程序都将拾取 Ant 的设置。如果您需要不同的值,请设置 fork=false 并在 <sysproperty> 元素中提供值。

如果您希望分叉进程拾取 Ant 的设置,请使用 <syspropertyset> 元素来传播正常的代理设置。以下属性集是一种数据类型,可以在 <java> 任务中引用,以传递当前值。

<propertyset id="proxy.properties">
  <propertyref prefix="java.net.useSystemProxies"/>
  <propertyref prefix="http."/>
  <propertyref prefix="https."/>
  <propertyref prefix="ftp."/>
  <propertyref prefix="socksProxy"/>
</propertyset>

总结和结论

有四种方法可以在 Ant 中设置代理。

  1. 使用 Ant 1.7 和 Java 5+ 使用 -autoproxy 参数。
  2. 通过 JVM 系统属性——在 ANT_ARGS 环境变量中设置这些属性。
  3. 通过 <setproxy> 任务。
  4. 自定义 ProxySelector 实现

代理设置会自动与在 Ant 下启动的未分叉的 Java 程序共享;要将代理设置传递给子程序,请使用属性集。

随着时间的推移,我们预计 Java 5+ 代理功能会稳定,并且 Java 代码会适应它们。但是,鉴于它目前确实会破坏一些构建,因此在 Ant 默认启用自动代理功能之前还需要一段时间。在此之前,您必须启用 -autoproxy 选项或使用其中一种替代机制来配置 JVM。

进一步阅读