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

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


当前回答

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

其他回答

以编程方式设置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使用浏览器代理设置的方法。你需要做的是将${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。如果有人知道如何克服这个限制,请告诉我。

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

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

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

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

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

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

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