如何设置JVM使用的代理

很多时候,一个Java应用程序需要连接到Internet。 最常见的例子是在读取XML文件时需要下载模式。

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

从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" 

以编程方式设置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 -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

你可以这样编程设置这些标志:

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

只需要从方法needsProxy()getProxyHost()getProxyPort()返回正确的值,你可以随时调用这个代码片段。

您可以将有关代理服务器的一些属性设置为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使用代理来进行HTTP调用

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

这可以使用用户设置代理

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

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

如果你指望通过互联网检索模式或DTD,你正在构建一个缓慢,琐碎,脆弱的应用程序。 当托管文件的远程服务器需要计划内或计划外的停机时会发生什么? 你的应用程序中断 这可以吗?

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

模式的URL等最好被认为是唯一的标识符。 不是作为远程实际访问该文件的请求。 做一些谷歌搜索“XML目录”。 XML目录允许您在本地托管这些资源,解决缓慢,烦躁和脆弱问题。

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

我也在防火墙后面,这对我工作!

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

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

export JAVA_TOOL_OPTIONS + =“-Djava.net.useSystemProxies = true”

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

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

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

这是一个时髦的例子:

 // 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

这对我行得通:

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

最近我发现了允许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 。 如果有人知道如何克服这个限制,让我知道。

以下显示了如何在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.proxyHost,https.proxyPort等。

如果你访问一个HTTP服务,你必须使用http.proxyHost,http.proxyPort等

结合Sorter和javabrett / Leonel的答案:

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

正如在其他答案中指出的那样,如果您需要使用Authenticated代理,那么纯粹使用命令行变量没有可靠的方法 – 如果您使用其他人的应用程序而不想混淆源代码。

请问艾弗森在使用HttpProxy连接到具有预先验证的主机时使用代理管理工具,如Proxifier( http://www.proxifier.com/for Mac OS X和Windows)来处理这个问题, 会提供有用的建议。

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

另外,如果您总是希望下载相同的模式,那么您可以将模式添加到您的类路径(文件系统或JAR),然后使用自定义的EntityResolver

请参阅此处以获取有关此方法的更完整讨论。

编辑:请参阅@ me.yahoo.com / a / 0QMxE关于使用EntityResolver方法的CatalogResolver 的讨论:

 CatalogResolver cr = new CatalogResolver(); ... yourParser.setEntityResolver(cr) 

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

我认为配置WINHTTP也将工作。

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