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

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

评论

关于此的Oracle文档似乎很陈旧(尽管可能仍然有效)。这是来自Spring的更现代的东西:docs.spring.io/spring-integration/reference/html/…

#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”)

– Tomalak
2010-12-21在19:44

嗨,大家好,您怎么也可以在其中包含用户名和密码?谢谢

–乔·布莱杰夫(Joeblackdev)
2011年3月1日在21:21

@Joeblackdev查看http.proxyUser和http.proxyPassword

–aasukisuki
2011年4月15日在20:06

@aasukisuki http.proxyUser和http.proxyPassword不是Java系统属性。它们用于Apache HTTP客户端。

–user207421
16年5月31日在2:54

另外,不要忘记为HTTPs配置https.proxyHost和https.proxyPort。

–C-Otto
16年7月26日在13:46

#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争论对我来说就像魅力一样。

– Nananosoft
2014年12月9日下午4:51

我使用此代码通过SSLSocket上的“ false”值禁用了代理。谢谢。


15年12月24日在11:19

也许是因为我的代理服务器需要身份验证,但是这对我不起作用。我希望做到了。

–西蒙·福斯伯格
19年3月19日在9:19

这不适用于代理自动配置(PAC)文件,请参阅stackoverflow.com/questions/10324996/…

– Michael_S
19年4月29日在10:55

#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?

–user207421
2011年4月8日在0:46

为什么不能识别“ con.setRequest ...”。为此需要什么库。

–随机数
2011年12月8日,0:03

袜子代理选项+1,因为有时HTTP代理无法解决我的问题

– manuzhang
13-10-17在5:34

在我的测试中,如果您仅设置默认的Authenticator,它就可以工作-无需设置身份验证属性

–德鲁·斯蒂芬斯(Drew Stephens)
2014年2月19日在16:05

如果仅系统属性,则不起作用。我认为java.net.socks。(username | password)属性没有任何作用。

–德鲁·斯蒂芬斯(Drew Stephens)
2014年2月19日下午16:11

#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()返回正确的值,就可以随时调用此代码段。

评论


“ proxySet”什么都不做。证明:将其设置为“ false”。尽管有各种书籍和在线参考资料,但JDK中没有而且从来没有这样的属性。它来自于早已灭亡的封装浏览器HotJavaBean,该死于1998年。

–user207421
2011年4月8日下午0:11

真的是没有http / https的属性名称吗?

–贝塔利斯塔
2012年4月23日在10:22

这在以下三个方面是错误的:1:如上所述,没有“ proxySet”项; 2:“ proxyHost”和“ proxyPort”必须为“ http.proxyHost”和“ http.proxyPort”(或等效的“ https”); 3:System.getProperties()。put(X,Y)与System.setProperty(X,Y)不同。除此之外,-很好的答案。

– Rob Cranfill
13年5月5日在22:26

几乎正确。请参阅:memorynotfound.com/configure-http-proxy-settings-java

–csvan
16年7月13日在8:05

@RobCranfill 1:“ proxySet”曾经是旧JDK所需要的非标准标志,但现在不再需要; 2:“ proxyHost”和“ proxyPort”可以工作,即“ http”。前缀只是将它们限制为HTTP协议(类似于“ https。”。),3:这里是正确的。

–toolforger
18年11月23日在5:42

#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(...)

–西蒙·福斯伯格
19年3月19日在9:24

#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

评论


这是行不通的。如果尚未通过身份验证,则main函数中的第一行将获得一堆空值,并且代码将停止。这无助于某人验证其jvm,以便他们可以通过代理进行URL调用。

–随机数
2011年12月8日,下午3:09

#8 楼

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


export 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客户端属性,因此,并非在所有情况下都有效。

– THelper
17年4月4日上午10:18

#10 楼


读取XML文件并需要下载其模式


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

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

URL的最好将模式等视为唯一标识符。并非要求实际远程访问该文件。做一些谷歌搜索“ XML目录”。 XML目录使您可以在本地托管此类资源,从而解决了缓慢性,聊天性和脆弱性。

它基本上是远程内容的永久缓存副本。没关系,因为远程内容永远不会改变。如果有更新,则将使用其他URL。使通过Internet进行资源的实际检索特别愚蠢。

#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.proxyUser和http.proxyPassword不是Java系统属性。它们用于Apache HTTP客户端。

–user207421
16年5月31日在2:57

使用System.setProperty代替System.getProperties()。put(...)

–西蒙·福斯伯格
19年3月19日在9:26

#14 楼

这是一个较小的更新,但是自Java 7起,现在可以以编程方式而不是通过系统属性来创建代理连接。如果在以下情况下这可能有用:


在程序运行时需要动态旋转代理
需要使用多个并行代理
或者只是使代码更简洁: )

这是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。

–user207421
16年5月31日在2:58

#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。

这种方法的唯一问题是,您需要使用bootclasspath中的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();

–鲍里斯(Boris)
2015年9月2日16:00



指向deploy.jar的xbootclasspath有什么作用,我不能将那个jar放在我的普通类路径中(在没有webstart的情况下运行)?

–豪特曼
18-2-20在14:51



在JDK 9中,它失败:(线程“ main”中的异常java.lang.IllegalAccessError:class ...)无法访问类com.sun.deploy.net.proxy.DeployProxySelector(在jdk.deploy模块中),因为模块jdk。部署不会导出com.sun.deploy.net.proxy

–豪特曼
18年2月20日在15:19

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

评论


该答案未提供其他答案中未提及的任何内容。

–西蒙·福斯伯格
19年3月19日在9:27

#17 楼

正如其他答案所指出的那样,如果您需要使用身份验证代理,则没有可靠的方法可以单纯使用命令行变量来执行此操作-如果您使用的是其他人的应用程序并且不想与源代码。

Iverson会在“使用HttpProxy使用预先身份验证连接到主机以使用代理管理工具(例如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 Updates在内的许多程序在代理背后都存在问题。通过设置WINHTTP,始终可以解决此类问题