如何设置JVM使用的代理

时间:2020-03-06 14:35:48  来源:igfitidea点击:

很多时候,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中的注释:

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。如果有人知道如何克服此限制,请告诉我。