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

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

有帮助吗?

解决方案

从Java文档(不是 javadoc API):

http://download.oracle.com/ JavaSE的/ 6 /文档/技术说明/指南/净/ 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 /文档/技术说明/引导件/


更新:如果您不想使用代理解析某些本地/内部网主机,请查看@Tomalak的评论:

  

另外请不要忘记http.nonProxyHosts属性!

-Dhttp.nonProxyHosts="localhost|127.0.0.1|10.*.*.*|*.foo.com‌​|etc"

其他提示

使用系统代理设置:

java -Djava.net.useSystemProxies=true ...

或以编程方式:

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

来源: http://docs.oracle的.com / JavaSE的/ 7 /文档/ API / JAVA /净/ DOC-文件/净properties.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代理在网络堆栈中的不同级别运行,因此您可以使用其中一个或两者。

您可以通过这种方式以编程方式设置这些标志:

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

只需从方法 needsProxy() getProxyHost() getProxyPort()中返回正确的值,然后就可以调用此代码段随时随地。

JVM使用代理进行HTTP调用

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

这可能会使用用户设置代理

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

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

结合分拣机和javabrett / Leonel的答案:

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

读取XML文件并需要下载其架构

如果您指望通过互联网检索模式或DTD,那么您正在构建一个缓慢,繁琐,脆弱的应用程序。当托管文件的远程服务器需要计划内或计划外停机时会发生什么?你的应用中断了。那可以吗?

请参阅 http://xml.apache .ORG /公地/组件/分解器/分解器article.html#s.catalog.files

模式等的URL最好被认为是唯一标识符。不是远程实际访问该文件的请求。做一些谷歌搜索“XML目录”。 XML目录允许您在本地托管此类资源,解决缓慢,烦躁和脆弱的问题。

它基本上是远程内容的永久缓存副本。这没关系,因为远程内容永远不会改变。如果有更新,它将在不同的URL。通过互联网实际检索资源尤其愚蠢。

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

  

导出JAVA_TOOL_OPTIONS + =&quot; -Djava.net.useSystemProxies =真QUOT;

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

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

以下显示了如何使用命令行中的代理用户和代理密码在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.proxyHost,https.proxyPort等。

如果您访问HTTP服务,则必须使用http.proxyHost,http.proxyPort等。

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

这是次要更新,但自Java 7以来,现在可以通过编程方式而不是通过系统属性创建代理连接。如果符合以下条件,这可能很有用:

  1. 代理需要在程序运行时动态旋转
  2. 需要使用多个并行代理
  3. 或者只是让你的代码更清洁:)
  4. 这是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

如果您想要“袜子代理”,请通知“socksProxyHost”。和“socksProxyPort” VM参数。

e.g。

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

最近,我发现了允许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:&quot;%JAVA_HOME%\ jre \ lib \ deploy.jar&quot; -jar my.jar 。如果有人知道如何克服这个限制,请告诉我。

这对我有用:

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的回答。

正如其他答案所指出的,如果你需要使用Authenticated代理,那么纯粹使用命令行变量就没有可靠的方法 - 如果你使用别人的应用程序并且不想弄乱了源代码。

Will Iverson 会在使用HttpProxy连接到具有preemtive身份验证的主机,以使用代理管理工具,如Proxifier( http://www.proxifier.com/ 适用于Mac OS X和Windows)来处理此问题。

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

此外,如果您总是希望下载相同的架构,那么您可以将架构添加到类路径(文件系统或JAR),然后使用自定义 EntityResolver

有关此方法的更完整讨论,请参见此处

编辑:请参阅使用CatalogResolver的 @ me.yahoo.com / a / 0QMxE 讨论EntityResolver方法:

CatalogResolver cr = new CatalogResolver();
...
yourParser.setEntityResolver(cr) 

如果您位于独立的JVM中,则可以使用http.proxy * JVM变量,但是您不应该修改其启动脚本和/或在应用程序服务器中执行此操作(jboss或tomcat除外)。相反,您应该使用JAVA代理API(而不是System.setProperty)或利用供应商自己的配置选项。 WebSphere和WebLogic都有非常明确的方法来设置比J2SE更强大的代理。此外,对于WebSphere和WebLogic,您可能会通过覆盖启动脚本(特别是服务器的互操作流程)来破坏您的应用程序服务器,因为您可能会告诉他们使用您的代理......

我认为配置 WINHTTP 也可以。

包括Windows更新在内的许多程序都存在代理问题。通过设置WINHTTP将始终解决这类问题

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top