如何设置JVM使用的代理
很多时候,Java应用程序需要连接到Internet。最常见的示例是在读取XML文件并需要下载其架构时发生的。
我在代理服务器后面。如何设置我的JVM使用代理?
解决方案
从Java文档(不是javadoc API)中:
http://download.oracle.com/javase/6/docs/technotes/guides/net/proxies.html
在命令行上启动JVM时,设置JVM标志http.proxyHost
和http.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中的注释:
Also don't forget the http.nonProxyHosts property!
-Dhttp.nonProxyHosts="localhost|127.0.0.1|10.*.*.*|*.foo.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()中返回正确的值,即可随时调用此代码段。
reading an XML file and needs to download its schema
如果我们指望通过Internet检索架构或者DTD,则我们正在构建一个缓慢,健谈,易碎的应用程序。当托管文件的远程服务器发生计划内或者计划外停机时,会发生什么情况?应用中断了。那样行吗?
参见http://xml.apache.org/commons/components/resolver/resolver-article.html#s.catalog.files
最好将模式等的URL视为唯一标识符。并非要求远程实际访问该文件。做一些谷歌搜索" XML目录"。 XML目录使我们可以在本地托管此类资源,从而解决了速度慢,聊天混乱和脆弱的问题。
它基本上是远程内容的永久缓存副本。没关系,因为远程内容永远不会改变。如果有更新,则将使用其他URL。使得通过Internet进行资源的实际检索特别愚蠢。
另外,如果我们始终希望下载相同的架构,则可以将该架构添加到类路径(文件系统或者JAR),然后使用自定义EntityResolver
有关此方法的更完整讨论,请参见此处。
编辑:请参阅@ me.yahoo.com / a / 0QMxE对CatalogResolver的讨论,该讨论使用EntityResolver方法:
CatalogResolver cr = new CatalogResolver(); ... yourParser.setEntityResolver(cr)
我们可以将有关代理服务器的某些属性设置为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; } }
范例.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
要以编程方式设置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代理在网络堆栈中的不同级别上运行,因此我们可以使用其中一个或者两个。
如果我们位于独立的JVM中,则可以使用http.proxy * 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。如果有人知道如何克服此限制,请告诉我。