如何将代理设置为JVM使用

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

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

782326 次浏览

从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.*.*.*|*.example.com|etc"

你可以通过编程的方式设置这些标志:

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

只要从方法needsProxy()getProxyHost()getProxyPort()中返回正确的值,你就可以在任何你想要的时候调用这个代码片段。

读取一个XML文件,并需要下载它的模式

如果您依赖于通过internet检索模式或dtd,那么您正在构建一个缓慢、频繁且脆弱的应用程序。当托管文件的远程服务器发生计划内或计划外停机时,会发生什么?你的应用程序崩溃了。这样可以吗?

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

模式和类似的URL最好被认为是唯一标识符。而不是远程访问文件的请求。在“XML目录”上做一些谷歌搜索。XML目录允许您在本地托管这些资源,从而解决了慢、多和脆弱的问题。

它基本上是远程内容的永久缓存副本。这是可以的,因为远程内容永远不会改变。如果有更新,也会是另一个网址。使得在互联网上实际检索资源变得特别愚蠢。

可以将代理服务器的一些属性设置为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 < / p >

以编程方式设置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代理在网络堆栈中的不同级别上操作,因此您可以使用其中一个或另一个,也可以同时使用两者。

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

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

我认为配置WINHTTP也可以。

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

使用系统代理设置:

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

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

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

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

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

将艾弗森使用HttpProxy连接到具有抢先认证的主机中提出了有用的建议,使用代理管理工具,如proxfier (http://www.proxifier.com/ for Mac OS X和Windows)来处理这个问题。

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

这对我来说很管用:

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使用代理进行HTTP调用

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

这可以使用用户设置代理

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

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

export JAVA_TOOL_OPTIONS+=" - djava.net.usesystemagents =true"

这是一个小更新,但是从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()
}
< p >全部参考: http://docs.oracle.com/javase/7/docs/technotes/guides/net/proxies.html < / p >

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

综合Sorter和javabrett/Leonel的回答:

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

如果你想要“Socks Proxy”,通知“socksProxyHost”和“socksProxyPort”虚拟机参数。

如。

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

这是一个对我有用的完整示例-注意,对于HTTPS有单独的属性(根据https://docs.oracle.com/javase/8/docs/technotes/guides/net/proxies.html)。

下面的代码向https://api.myip.com API发送请求并打印响应。

public static void main(String[] args) throws IOException {
System.setProperty("java.net.useSystemProxies", "true");
final String proxyUser = "lum-customer-c_f95783f5-zone-datacenter-ip-92.240.207.56";
final String proxyPass = "s3mgwrx2b628";
final String host = "zproxy.lum-superproxy.io";
final Integer port = 22225;


// http
System.setProperty("http.proxyHost",host);
System.setProperty("http.proxyPort", String.valueOf(port));
System.setProperty("http.proxyUser", proxyUser);
System.setProperty("http.proxyPassword", proxyPass);


// https
System.setProperty("https.proxyHost",host);
System.setProperty("https.proxyPort", String.valueOf(port));
System.setProperty("https.proxyUser", proxyUser);
System.setProperty("https.proxyPassword", proxyPass);


System.setProperty("jdk.http.auth.tunneling.disabledSchemes", "");
System.setProperty("jdk.https.auth.tunneling.disabledSchemes", "");


Authenticator.setDefault(new Authenticator() {
@Override
public PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(proxyUser, proxyPass.toCharArray());
}
}
);


// create and send a https request to myip.com API
URL url = new URL("https://api.myip.com");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
int status = connection.getResponseCode();
    

// read the response
BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
String responseLine;
StringBuffer responseContent = new StringBuffer();
while ((responseLine = in.readLine()) != null)
responseContent.append(responseLine);
    

in.close();
connection.disconnect();
    

// print the response
System.out.println(status);
System.out.println(responseContent);
}