344

很多时候,Java 应用程序需要连接到 Internet。最常见的示例发生在读取 XML 文件并需要下载其模式时。

我在代理服务器后面。如何设置我的 JVM 以使用代理?

4

19 回答 19

382

从 Java 文档(不是javadoc API):

http://download.oracle.com/javase/6/docs/technotes/guides/net/proxies.html

设置 JVM 标志http.proxyHost以及http.proxyPort在命令行上启动 JVM 时。这通常在 shell 脚本(在 Unix 中)或 bat 文件(在 Windows 中)中完成。这是 Unix shell 脚本的示例:

JAVA_FLAGS=-Dhttp.proxyHost=10.0.0.100 -Dhttp.proxyPort=8800
java ${JAVA_FLAGS} ...

在使用 JBoss 或 WebLogic 等容器时,我的解决方案是编辑供应商提供的启动脚本。

许多开发人员都熟悉 Java API (javadocs),但很多时候文档的其余部分被忽略了。它包含很多有趣的信息:http: //download.oracle.com/javase/6/docs/technotes/guides/


更新:如果您不想使用代理来解析某些本地/内网主机,请查看@Tomalak 的评论:

也不要忘记 http.nonProxyHosts 属性!

-Dhttp.nonProxyHosts="localhost|127.0.0.1|10.*.*.*|*.foo.com‌​|etc"
于 2008-09-23T12:54:23.010 回答
122

要使用系统代理设置:

java -Djava.net.useSystemProxies=true ...

或以编程方式:

System.setProperty("java.net.useSystemProxies", "true");

来源:http ://docs.oracle.com/javase/7/docs/api/java/net/doc-files/net-properties.html

于 2012-07-17T17:13:27.123 回答
88

以编程方式设置 HTTP/HTTPS 和/或 SOCKS 代理:

...

public void setProxy() {
    if (isUseHTTPProxy()) {
        // HTTP/HTTPS Proxy
        System.setProperty("http.proxyHost", getHTTPHost());
        System.setProperty("http.proxyPort", getHTTPPort());
        System.setProperty("https.proxyHost", getHTTPHost());
        System.setProperty("https.proxyPort", getHTTPPort());
        if (isUseHTTPAuth()) {
            String encoded = new String(Base64.encodeBase64((getHTTPUsername() + ":" + getHTTPPassword()).getBytes()));
            con.setRequestProperty("Proxy-Authorization", "Basic " + encoded);
            Authenticator.setDefault(new ProxyAuth(getHTTPUsername(), getHTTPPassword()));
        }
    }
    if (isUseSOCKSProxy()) {
        // SOCKS Proxy
        System.setProperty("socksProxyHost", getSOCKSHost());
        System.setProperty("socksProxyPort", getSOCKSPort());
        if (isUseSOCKSAuth()) {
            System.setProperty("java.net.socks.username", getSOCKSUsername());
            System.setProperty("java.net.socks.password", getSOCKSPassword());
            Authenticator.setDefault(new ProxyAuth(getSOCKSUsername(), getSOCKSPassword()));
        }
    }
}

...

public class ProxyAuth extends Authenticator {
    private PasswordAuthentication auth;

    private ProxyAuth(String user, String password) {
        auth = new PasswordAuthentication(user, password == null ? new char[]{} : password.toCharArray());
    }

    protected PasswordAuthentication getPasswordAuthentication() {
        return auth;
    }
}

...

请记住,HTTP 代理和 SOCKS 代理在网络堆栈中的不同级别运行,因此您可以使用其中一个或两个或两者。

于 2008-09-26T00:50:42.753 回答
49

您可以通过以下方式以编程方式设置这些标志:

if (needsProxy()) {
    System.setProperty("http.proxyHost",getProxyHost());
    System.setProperty("http.proxyPort",getProxyPort());
} else {
    System.setProperty("http.proxyHost","");
    System.setProperty("http.proxyPort","");
}

只需从方法needsProxy()中返回正确的值getProxyHost()getProxyPort()您就可以随时调用此代码片段。

于 2008-09-23T12:57:48.257 回答
26

JVM 使用代理进行 HTTP 调用

System.getProperties().put("http.proxyHost", "someProxyURL");
System.getProperties().put("http.proxyPort", "someProxyPort");

这可能会使用用户设置代理

System.setProperty("java.net.useSystemProxies", "true");
于 2015-01-13T09:49:26.803 回答
15

结合 Sorter 和 javabrett/Leonel 的答案:

java -Dhttp.proxyHost=10.10.10.10 -Dhttp.proxyPort=8080 -Dhttp.proxyUser=username -Dhttp.proxyPassword=password -jar myJar.jar
于 2017-07-12T14:12:28.360 回答
12

您可以将有关代理服务器的一些属性设置为 jvm 参数

-Dhttp.proxyPort=8080、proxyHost等

但是如果您需要通过身份验证代理,则需要像以下示例一样的身份验证器:

ProxyAuthenticator.java

import java.net.*;
import java.io.*;

public class ProxyAuthenticator extends Authenticator {

    private String userName, password;

    protected PasswordAuthentication getPasswordAuthentication() {
        return new PasswordAuthentication(userName, password.toCharArray());
    }

    public ProxyAuthenticator(String userName, String password) {
        this.userName = userName;
        this.password = password;
    }
}

Example.java

    import java.net.Authenticator;
    import ProxyAuthenticator;

public class Example {

    public static void main(String[] args) {
        String username = System.getProperty("proxy.authentication.username");
        String password = System.getProperty("proxy.authentication.password");

                if (username != null && !username.equals("")) {
            Authenticator.setDefault(new ProxyAuthenticator(username, password));
        }

                // here your JVM will be authenticated

    }
}

基于此回复: http: //mail-archives.apache.org/mod_mbox/jakarta-jmeter-user/200208.mbox/%3C494FD350388AD511A9DD00025530F33102F1DC2C@MMSX006%3E

于 2008-09-23T17:48:36.453 回答
12

java.net.useSystemProxies属性设置为true。例如,您可以通过JAVA_TOOL_OPTIONS环境变量来设置它。例如,在 Ubuntu 中,您可以将以下行添加到.bashrc

导出 JAVA_TOOL_OPTIONS+="-Djava.net.useSystemProxies=true"

于 2015-09-10T21:25:27.140 回答
11

下面展示了如何在 Java中从命令行使用代理用户和代理密码设置代理,这是一种非常常见的情况。首先,您不应该在代码中保存密码和主机。

使用 -D 在命令行中传递系统属性并使用 System.setProperty("name", "value") 在代码中设置它们是等效的。

但请注意这一点

有效的例子:

C:\temp>java -Dhttps.proxyHost=host -Dhttps.proxyPort=port -Dhttps.proxyUser=user -Dhttps.proxyPassword="password" -Djavax.net.ssl.trustStore=c:/cacerts -Djavax.net.ssl.trustStorePassword=changeit com.andreas.JavaNetHttpConnection

但以下不起作用

C:\temp>java com.andreas.JavaNetHttpConnection -Dhttps.proxyHost=host -Dhttps.proxyPort=port -Dhttps=proxyUser=user -Dhttps.proxyPassword="password" -Djavax.net.ssl.trustStore=c:/cacerts -Djavax.net.ssl.trustStorePassword=changeit

唯一不同的是系统属性的位置!(课前和课后)

如果您的密码中有特殊字符,您可以将其放在引号“@MyPass123%”中,如上例所示。

如果您访问 HTTPS 服务,则必须使用https.proxyHosthttps.proxyPort

如果访问 HTTP 服务,则必须使用http.proxyHosthttp.proxyPort

于 2017-01-25T21:47:21.317 回答
8

读取 XML 文件并需要下载其架构

如果您指望通过 Internet 检索模式或 DTD,那么您正在构建一个缓慢、健谈、脆弱的应用程序。当托管文件的远程服务器发生计划内或计划外停机时会发生什么?您的应用程序中断。那样可以么?

请参阅http://xml.apache.org/commons/components/resolver/resolver-article.html#s.catalog.files

架构等的 URL 最好被视为唯一标识符。不像请求实际远程访问该文件。在“XML 目录”上做一些谷歌搜索。XML 目录允许您在本地托管此类资源,从而解决缓慢、繁琐和脆弱的问题。

它基本上是远程内容的永久缓存副本。没关系,因为远程内容永远不会改变。如果有更新,它将位于不同的 URL。通过互联网实际检索资源特别愚蠢。

于 2008-09-23T17:09:09.167 回答
7

我也在防火墙后面,这对我有用!

System.setProperty("http.proxyHost", "proxy host addr");
System.setProperty("http.proxyPort", "808");
Authenticator.setDefault(new Authenticator() {
    protected PasswordAuthentication getPasswordAuthentication() {

        return new PasswordAuthentication("domain\\user","password".toCharArray());
    }
});

URL url = new URL("http://www.google.com/");
URLConnection con = url.openConnection();

BufferedReader in = new BufferedReader(new InputStreamReader(
                    con.getInputStream()));

// Read it ...
String inputLine;
while ((inputLine = in.readLine()) != null)
    System.out.println(inputLine);

in.close();
于 2012-09-06T07:37:07.523 回答
6

如果您想要“Socks 代理”,请通知“socksProxyHost”和“socksProxyPort”VM 参数。

例如

java -DsocksProxyHost=127.0.0.1 -DsocksProxyPort=8080 org.example.Main
于 2017-11-30T22:02:05.543 回答
4

在连接到代理后面的 URL 之前添加它。

System.getProperties().put("http.proxyHost", "someProxyURL");
System.getProperties().put("http.proxyPort", "someProxyPort");
System.getProperties().put("http.proxyUser", "someUserName");
System.getProperties().put("http.proxyPassword", "somePassword");
于 2012-10-21T06:17:29.793 回答
4

这是一个小更新,但从 Java 7 开始,代理连接现在可以通过编程而不是通过系统属性来创建。如果出现以下情况,这可能很有用:

  1. 代理需要在程序运行时动态旋转
  2. 需要使用多个并行代理
  3. 或者只是让你的代码更干净:)

这是 groovy 中的一个人为示例:

// proxy configuration read from file resource under "proxyFileName"
String proxyFileName = "proxy.txt"
String proxyPort = "1234"
String url = "http://www.promised.land"
File testProxyFile = new File(proxyFileName)
URLConnection connection

if (!testProxyFile.exists()) {

    logger.debug "proxyFileName doesn't exist.  Bypassing connection via proxy."
    connection = url.toURL().openConnection()

} else {
    String proxyAddress = testProxyFile.text
    connection = url.toURL().openConnection(new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxyAddress, proxyPort)))
}

try {
    connection.connect()
}
catch (Exception e) {
    logger.error e.printStackTrace()
}

完整参考: http ://docs.oracle.com/javase/7/docs/technotes/guides/net/proxies.html

于 2015-10-01T22:34:41.707 回答
3

最近我发现了允许 JVM 使用浏览器代理设置的方法。您需要做的是添加${java.home}/lib/deploy.jar到您的项目并初始化库,如下所示:

import com.sun.deploy.net.proxy.DeployProxySelector;
import com.sun.deploy.services.PlatformType;
import com.sun.deploy.services.ServiceManager;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public abstract class ExtendedProxyManager {

    private static final Log logger = LogFactory.getLog(ExtendedProxyManager.class);

    /**
     * After calling this method, proxy settings can be magically retrieved from default browser settings.
     */
    public static boolean init() {
        logger.debug("Init started");

        // Initialization code was taken from com.sun.deploy.ClientContainer:
        ServiceManager
                .setService(System.getProperty("os.name").toLowerCase().indexOf("windows") != -1 ? PlatformType.STANDALONE_TIGER_WIN32
                        : PlatformType.STANDALONE_TIGER_UNIX);

        try {
            // This will call ProxySelector.setDefault():
            DeployProxySelector.reset();
        } catch (Throwable throwable) {
            logger.error("Unable to initialize extended dynamic browser proxy settings support.", throwable);

            return false;
        }

        return true;
    }
}

之后,代理设置可通过java.net.ProxySelector.

这种方法的唯一问题是您需要deploy.jar在 bootclasspath 中启动 JVM,例如java -Xbootclasspath/a:"%JAVA_HOME%\jre\lib\deploy.jar" -jar my.jar. 如果有人知道如何克服这个限制,请告诉我。

于 2010-03-09T14:18:11.493 回答
3

这对我行得通:

public void setHttpProxy(boolean isNeedProxy) {
    if (isNeedProxy) {
        System.setProperty("http.proxyHost", getProxyHost());
        System.setProperty("http.proxyPort", getProxyPort());
    } else {
        System.clearProperty("http.proxyHost");
        System.clearProperty("http.proxyPort");
    }
}

P/S:我基于 GHad 的回答。

于 2014-07-03T10:43:23.393 回答
1

正如其他答案中指出的那样,如果您需要使用经过身份验证的代理,则没有可靠的方法来纯粹使用命令行变量来做到这一点 - 如果您使用的是其他人的应用程序并且不想弄乱源代码。

Will IversonUsing HttpProxy to connect to a host with preemtive authentication中提出了有用的建议,以使用Proxifier 等代理管理工具( Mac OS X 和 Windows 为http://www.proxifier.com/)来处理这个问题。

例如,使用 Proxifier,您可以将其设置为仅拦截要通过其(经过身份验证的)代理管理和重定向的 java 命令。不过,在这种情况下,您需要将 proxyHost 和 proxyPort 值设置为空白,例如传入-Dhttp.proxyHost= -Dhttp.proxyPort=您的 java 命令。

于 2012-12-20T07:22:49.040 回答
-1

如果您在独立的 JVM 中,您可以使用 http.proxy* JVM 变量,但您不应该修改它们的启动脚本和/或在您的应用程序服务器中执行此操作(可能除了 jboss 或 tomcat)。相反,您应该使用 JAVA 代理 API(而不是 System.setProperty)或使用供应商自己的配置选项。WebSphere 和 WebLogic 都有非常明确的方法来设置比 J2SE 强大得多的代理。此外,对于 WebSphere 和 WebLogic,您可能会通过覆盖启动脚本(特别是服务器的互操作进程,因为您可能会告诉他们也使用您的代理...)来破坏您的应用程序服务器。

于 2010-02-23T19:46:31.803 回答
-5

我认为配置WINHTTP也可以。

包括 Windows 更新在内的许多程序都存在代理问题。通过设置WINHTTP总会解决这类问题

于 2011-11-03T20:48:10.087 回答