Java 设置 JVM/JRE 以自动使用 Windows 代理

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/376101/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 14:01:31  来源:igfitidea点击:

Setting JVM/JRE to use Windows Proxy Automatically

javaproxyjvm

提问by t3rse

I did see the question about setting the proxy for the JVM but what I want to ask is how one can utilize the proxy that is already configured (on Windows).

我确实看到了关于为 JVM 设置代理的问题,但我想问的是如何利用已经配置的代理(在 Windows 上)。

Here is a demonstration of my issue:

这是我的问题的演示:

  1. Go to your Control Panel->Java and set a proxy address.
  2. Run the following simple applet code (I'm using the Eclipse IDE):
  1. 转到您的控制面板-> Java 并设置代理地址。
  2. 运行以下简单的小程序代码(我使用的是 Eclipse IDE):
import java.awt.Graphics;
import javax.swing.JApplet;
import java.util.*;

public class Stacklet extends JApplet {
    private String message;
    public void init(){
        Properties props = System.getProperties();
        message = props.getProperty("http.proxyHost", "NONE");      
        message = (message.length() == 0)? "NONE": message;
    }

    public void paint(Graphics g)
    {
        g.drawString(message, 20, 20);
    }
}

The Applet displays "NONE" without regard to the settings you've placed in the Java Control Panel. What would be best would be if the Windows proxy settings (usually set in Internet Explorer) were what I could determine but doing an extra configuration step in the Java Control Panel would still be an acceptable solution.

Applet 显示“NONE”而不考虑您在 Java 控制面板中的设置。如果 Windows 代理设置(通常在 Internet Explorer 中设置)是我可以确定的,但在 Java 控制面板中执行额外的配置步骤仍然是可接受的解决方案,那将是最好的。

Thanks!

谢谢!

采纳答案by t3rse

It is possible to detect the proxy using the ProxySelectorclass and assign the system proxy by assigning environment variables with the setProperty method of the System class:

可以使用ProxySelector类检测代理并通过使用System 类setProperty 方法分配环境变量来分配系统代理:

System.setProperty("java.net.useSystemProxies", "true");
System.out.println("detecting proxies");
List l = null;
try {
    l = ProxySelector.getDefault().select(new URI("http://foo/bar"));
} 
catch (URISyntaxException e) {
    e.printStackTrace();
}
if (l != null) {
    for (Iterator iter = l.iterator(); iter.hasNext();) {
        java.net.Proxy proxy = (java.net.Proxy) iter.next();
        System.out.println("proxy type: " + proxy.type());

        InetSocketAddress addr = (InetSocketAddress) proxy.address();

        if (addr == null) {
            System.out.println("No Proxy");
        } else {
            System.out.println("proxy hostname: " + addr.getHostName());
            System.setProperty("http.proxyHost", addr.getHostName());
            System.out.println("proxy port: " + addr.getPort());
            System.setProperty("http.proxyPort", Integer.toString(addr.getPort()));
        }
    }
}

回答by Alain O'Dea

UPDATE:you need to have the System Property java.net.useSystemProxiesset to truefor my solution below to work.

更新:您需要将系统属性java.net.useSystemProxies设置为true才能使下面的解决方案起作用。

If you use java.net.URL.openStream()to get an InputStreamfor the web resource content you automatically get the same proxy used as Internet Explorer would use for that URL.

如果您用于java.net.URL.openStream()获取InputStreamWeb 资源内容的 ,您会自动获取 Internet Explorer 用于该 URL 的相同代理。

No need to go to the Java Control Panel or to display the proxy used.

无需转到 Java 控制面板或显示使用的代理。

回答by Hrvoje

java.net.URL.openStream()is a shorthand for java.net.URL.openConnection().getInputStream().

java.net.URL.openStream()是 的简写java.net.URL.openConnection().getInputStream()

回答by Flo

I found an odd behavior experimenting with the suggested code here.

我在此处尝试使用建议的代码时发现了一种奇怪的行为。

It appears that, after a default ProxySelector has been set, regular socket code (e.g. creating a new Socket) does not work anymore, because it tries to use a socks server (not sure why it would do this, but for me it does).

看起来,在设置了默认的 ProxySelector 之后,常规套接字代码(例如,创建一个新的套接字)不再起作用,因为它尝试使用袜子服务器(不知道为什么会这样做,但对我来说确实如此) .

So if you, when calling

所以如果你在打电话时

Socket socket = new Socket(host, port);

you receive such a SocketException:

您收到这样的 SocketException:

java.net.SocketException: Malformed reply from SOCKS server
    at java.net.SocksSocketImpl.readSocksReply(Unknown Source)
    at java.net.SocksSocketImpl.connect(Unknown Source)
    at java.net.Socket.connect(Unknown Source)
    at java.net.Socket.connect(Unknown Source)
    at java.net.Socket.<init>(Unknown Source)
    at java.net.Socket.<init>(Unknown Source)

then try setting the default ProxySelector back to null:

然后尝试将默认的 ProxySelector 设置回 null:

ProxySelector.setDefault(null);

For me this resulted in the following small Java class which I now use to simply retrieve the systems proxy settings without having it affect the further usage of Sockets() of the application, yet configuring the system properly to use the proxy:

对我来说,这导致了以下小 Java 类,我现在使用它来简单地检索系统代理设置,而不会影响应用程序的 Sockets() 的进一步使用,但正确配置系统以使用代理:

public class ProxyConfig {

  private static String host;
  private static int port;

  public static void init() {
    System.setProperty("java.net.useSystemProxies", "true");
    Proxy proxy = getProxy();
    if (proxy != null) {
      InetSocketAddress addr = (InetSocketAddress) proxy.address();
      host = addr.getHostName();
      port = addr.getPort();

      System.setProperty("java.net.useSystemProxies", "false");
      System.setProperty("http.proxyHost", host);
      System.setProperty("http.proxyPort", ""+port);

    }
    System.setProperty("java.net.useSystemProxies", "false");
  }

  public static String getHost() {
    return host;
  }

  public static int getPort() {
    return port;
  }

  private static Proxy getProxy() {
    List<Proxy> l = null;
    try {
      ProxySelector def = ProxySelector.getDefault();

      l = def.select(new URI("http://foo/bar"));
      ProxySelector.setDefault(null);
    } catch (Exception e) {
      e.printStackTrace();
    }
    if (l != null) {
      for (Iterator<Proxy> iter = l.iterator(); iter.hasNext();) {
        java.net.Proxy proxy = iter.next();
        return proxy;
      }
    }
    return null;
  }
}

回答by Juan Martin Lichowski

This might be a little late, but I ran into the same problem. The way I fixed it is by adding the following system property:

这可能有点晚了,但我遇到了同样的问题。我修复它的方法是添加以下系统属性:

-Djava.net.useSystemProxies=true

Now, note that this property is set only once at startup, so it can't change when you run your application. From https://docs.oracle.com/javase/7/docs/api/java/net/doc-files/net-properties.html#Proxies:

现在请注意,此属性仅在启动时设置一次,因此在您运行应用程序时无法更改。从https://docs.oracle.com/javase/7/docs/api/java/net/doc-files/net-properties.html#Proxies

java.net.useSystemProxies (default: false) ... Note that this property is checked only once at startup.

java.net.useSystemProxies (default: false) ... 请注意,此属性仅在启动时检查一次。

回答by Mahdi

try{
    System.setProperty("java.net.useSystemProxies", "true");
    String prx = ProxySelector.getDefault().select(new URI("http://www.google.com")).get(0).address().toString();
    JOptionPane.showMessageDialog(null, prx);
} catch(Exception e){
    JOptionPane.showMessageDialog(null, "no proxy");
}