很多时候,Java应用程序需要连接到Internet。最常见的例子发生在读取XML文件并需要下载其模式时。
我在代理服务器后面。如何将JVM设置为使用代理?
很多时候,Java应用程序需要连接到Internet。最常见的例子发生在读取XML文件并需要下载其模式时。
我在代理服务器后面。如何将JVM设置为使用代理?
当前回答
以编程方式设置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代理在网络堆栈中的不同级别上操作,因此您可以使用其中一个或另一个,也可以同时使用两者。
其他回答
正如在其他回答中指出的那样,如果您需要使用经过身份验证的代理,纯粹使用命令行变量是没有可靠的方法来做到这一点的——如果您正在使用别人的应用程序,并且不想弄乱源代码,这是很烦人的。
Will Iverson在使用HttpProxy连接到具有抢先身份验证的主机上提出了有用的建议,使用代理管理工具如proxfier (http://www.proxifier.com/ for Mac OS X和Windows)来处理这个问题。
例如,使用proxfier,您可以将其设置为仅拦截要通过其(经过身份验证的)代理进行管理和重定向的java命令。在这种情况下,你需要将proxyHost和proxyPort的值设置为空,例如传入-Dhttp。proxyHost = -Dhttp。proxyPort=到您的java命令。
综合Sorter和javabrett/Leonel的回答:
java -Dhttp.proxyHost=10.10.10.10 -Dhttp.proxyPort=8080 -Dhttp.proxyUser=username -Dhttp.proxyPassword=password -jar myJar.jar
最近,我发现了允许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 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
以编程方式设置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代理在网络堆栈中的不同级别上操作,因此您可以使用其中一个或另一个,也可以同时使用两者。