【问题标题】:How do I set the proxy to be used by the JVM如何设置 JVM 使用的代理
【发布时间】:2010-09-12 08:34:33
【问题描述】:

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

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

【问题讨论】:

标签: java proxy jvm


【解决方案1】:

来自 Java 文档(不是 javadoc API):

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

在命令行启动 JVM 时设置 JVM 标志 http.proxyHosthttp.proxyPort。 这通常在 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"

【讨论】:

  • +1。也不要忘记http.nonProxyHosts 属性! (像这样使用:-Dhttp.nonProxyHosts="localhost|127.0.0.1|10.*.*.*|*.foo.com|etc"
  • 大家好,你们怎么能把用户名和密码也包括在内呢?谢谢
  • @Joeblackdev 查看 http.proxyUser 和 http.proxyPassword
  • @aasukisuki http.proxyUserhttp.proxyPassword 不是 Java 系统属性。它们用于 Apache HTTP 客户端。
  • 另外,不要忘记为 HTTPs 配置 https.proxyHosthttps.proxyPort
【解决方案2】:

使用系统代理设置:

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

【讨论】:

  • 真棒设置 jvm 争论对我来说就像魅力一样。谢谢
  • 我使用此代码通过 SSLSocket 上的“false”值禁用代理。谢谢。
  • 可能是因为我的代理需要身份验证,但这对我不起作用。我希望是的。
  • 这不适用于代理自动配置 (PAC) 文件,请参阅 stackoverflow.com/questions/10324996/…
【解决方案3】:

以编程方式设置 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 代理在网络堆栈中的不同级别运行,因此您可以使用其中一种或两种。

【讨论】:

  • 如果设置了“java.net.socks.username/password”,为什么还要设置Authenticator?
  • 为什么“con.setRequest...”这个 con 无法识别。为此需要哪些库。
  • socks 代理选项 +1,因为有时 http 代理无法解决我的问题
  • 在我的测试中,如果你只设置默认的Authenticator,它就可以工作——不需要设置身份验证属性
  • 只有系统属性时不起作用。我认为 java.net.socks.(username|password) 属性什么都不做。
【解决方案4】:

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

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

只需从方法 needsProxy()getProxyHost()getProxyPort() 返回正确的值,您可以随时调用此代码 sn-p。

【讨论】:

  • "proxySet" 什么都不做。证明:将其设置为“假”。 JDK 中没有也从未有过这样的属性,尽管有各种书籍和在线参考资料。它来自早已不复存在的 HotJavaBean,一个封装的浏览器,在 1998 年左右死亡。
  • 真的是没有http/https的属性名吗?
  • 这在三个方面是错误的: 1:如前所述,没有“proxySet”项; 2:“proxyHost”和“proxyPort”需要是“http.proxyHost”和“http.proxyPort”(或“https”等价物); 3:System.getProperties().put(X,Y) 与 System.setProperty(X,Y) 相同。但除此之外 - 很好的答案。
  • @RobCranfill 1:“proxySet”曾经是旧 JDK 需要但不再需要的非标准标志; 2:“proxyHost”和“proxyPort”确实有效,“http”。前缀只是将它们限制为 HTTP 协议(​​类似于“https。”),3:你是对的。
【解决方案5】:

JVM 使用代理进行 HTTP 调用

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

这可能使用用户设置代理

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

【讨论】:

  • 使用System.setProperty 而不是System.getProperties().put(...)
【解决方案6】:

结合 Sorter 和 javabrett/Leonel 的答案:

java -Dhttp.proxyHost=10.10.10.10 -Dhttp.proxyPort=8080 -Dhttp.proxyUser=username -Dhttp.proxyPassword=password -jar myJar.jar

【讨论】:

    【解决方案7】:

    你可以设置一些关于代理服务器的属性作为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

    【讨论】:

    • 这不起作用。如果您尚未通过身份验证,则主函数中的第一行将获得一堆空值并且代码停止。这并不能帮助某人验证他们的 jvm,以便他们可以通过代理进行 URL 调用。
    【解决方案8】:

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

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

    【讨论】:

      【解决方案9】:

      下面展示了如何在 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 等。

      【讨论】:

      • ProxyUser 和 proxyPassword 不是 Java 系统属性,而是 Apache HTTP 客户端属性,因此并非在所有情况下都有效。
      【解决方案10】:

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

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

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

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

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

      【讨论】:

        【解决方案11】:

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

        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();
        

        【讨论】:

          【解决方案12】:

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

          例如

          java -DsocksProxyHost=127.0.0.1 -DsocksProxyPort=8080 org.example.Main
          

          【讨论】:

            【解决方案13】:

            在连接到代理后面的 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");
            

            【讨论】:

            • http.proxyUserhttp.proxyPassword 不是 Java 系统属性。它们用于 Apache HTTP 客户端。
            • 使用System.setProperty 而不是System.getProperties().put(...)
            【解决方案14】:

            这是一个小更新,但从 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

            【讨论】:

            • 这是从 Java 1.5 开始,而不是 1.7。
            【解决方案15】:

            最近我发现了允许 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 提供给 Java API。

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

            【讨论】:

            • 我希望我能多次投票,这是唯一对我有用的解决方案;谢谢!我必须从这里下载 apache commons 日志记录 jar:commons.apache.org/proper/commons-logging/download_logging.cgi 我在 Main() 中的代码:System.setProperty("java.net.useSystemProxies", "true"); System.out.println("检测代理"); ExtendedProxyManager.init();
            • xbootclasspath 指向 deploy.jar 会有什么影响,我不能把那个 jar 放到我的正常类路径中(在没有 webstart 的情况下运行)?
            • 在 JDK 9 中,它失败了 :( Exception in thread "main" java.lang.IllegalAccessError: class ...) cannot access class com.sun.deploy.net.proxy.DeployProxySelector (in module jdk.deploy) because module jdk.deploy does not export com.sun.deploy.net.proxy
            【解决方案16】:

            这对我有用:

            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 的回答。

            【讨论】:

            • 此答案未提供其他答案中尚未提及的任何内容。
            【解决方案17】:

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

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

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

            【讨论】:

              【解决方案18】:

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

              【讨论】:

                【解决方案19】:

                我认为配置WINHTTP 也可以。

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

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 2010-09-27
                  • 1970-01-01
                  • 2019-01-05
                  • 2016-09-14
                  • 1970-01-01
                  • 2016-08-19
                  • 1970-01-01
                  相关资源
                  最近更新 更多