【问题标题】:Setting JVM/JRE to use Windows Proxy Automatically将 JVM/JRE 设置为自动使用 Windows 代理
【发布时间】:2010-09-27 10:15:23
【问题描述】:

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

这是我的问题的演示:

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

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

谢谢!

【问题讨论】:

    标签: java proxy jvm


    【解决方案1】:

    可以使用ProxySelector类检测代理,并通过使用setProperty method of the System class分配环境变量来分配系统代理:

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

    【讨论】:

    • 我这里有代理。但是这段代码打印出“检测代理代理主机名:DIRECT No Proxy”,但实际上连接到指定的 URI 失败并超时。
    • proxy hostname : DIRECT No Proxy 这是否意味着我不在代理后面?
    • 同样的情况,我在代理后面,但我使用此代码得到 DIRECT No Proxy...
    • java.net.useSystemProxies 并不总是有效。我不知道它什么都不做的所有情况,但是如果代理是透明的,它肯定不会做任何事情,即应用程序只是直接连接,代理会在不告诉他们的情况下拦截该连接。
    【解决方案2】:

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

    -Djava.net.useSystemProxies=true
    

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

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

    【讨论】:

    • +1 提到这个属性只在启动时检查一次,在这个问题的其他任何地方都没有提到。
    • 其实如果指定了这个属性会自动使用系统代理!
    • 这不适用于代理自动配置 (PAC) 文件,请参阅 stackoverflow.com/questions/10324996/…
    【解决方案3】:

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

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

    所以如果你在打电话的时候

    Socket socket = new Socket(host, port);
    

    你收到这样的 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)
    

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

    ProxySelector.setDefault(null);
    

    对我来说,这导致了以下小型 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;
      }
    }
    

    【讨论】:

      【解决方案4】:

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

      【讨论】:

        【解决方案5】:

        更新:您需要将系统属性 java.net.useSystemProxies 设置为 true,我的以下解决方案才能正常工作。 p>

        如果您使用 java.net.URL.openStream() 为 Web 资源内容获取 InputStream,您将自动获得与 Internet Explorer 用于该 URL 的相同代理。

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

        【讨论】:

        • 不——这不是真的。或者,如果它应该以这种方式工作,它就不起作用。
        • @mmo 你是对的。感谢您确定这一点。我正在使用 java.net.useSystemProxies 并忘记提及这一点。这是一个要点。
        • @mmo 我是否已经充分解决了您的担忧,以便您删除反对票?
        【解决方案6】:
        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");
        }
        

        【讨论】:

        • 您好,欢迎来到 SO。您的答案仅包含代码。如果您还可以添加一些评论来解释它的作用和方式,那就更好了。你能请edit你的答案并添加吗?谢谢!
        猜你喜欢
        • 2010-09-12
        • 2023-04-05
        • 1970-01-01
        • 2016-08-19
        • 1970-01-01
        • 1970-01-01
        • 2010-09-16
        • 2019-01-05
        相关资源
        最近更新 更多