1

我正在编写要在 Windows 上运行的 Java (1.7) 应用程序。该应用程序正在访问在同一主机上运行的其他服务以及在Internet 中运行的其他服务。应用程序可以运行在两种环境中,一种是必须指定代理设置(访问互联网时有代理);而在其他环境中,则不得指定代理设置(没有代理)。

我希望应用程序简单,并且不希望其用户为 cmd 行(-Dhttp.proxyHost 等)上的代理设置规范而烦恼 - 应用程序应该从 Windows 系统设置(IE / 工具)中学习代理设置/ Internet 属性 / 连接 / LAN 设置)。

我已经编写了一段应该学习该设置的代码,见下文。问题是这段代码没有将localhost127.0.0.1my-computer-name(其中 my-computer-name 是我的计算机的名称)识别为在访问时应该绕过代理的 URL(是的,我确实选中了“绕过本地地址的代理服务器”)。结果,应用程序尝试通过错误的代理访问本地服务

到目前为止,我发现教 JVM 不使用“本地地址”代理的一种方法是在代理设置/例外中列出字符串(localhost、127.0.0.1、my-computer-name)(不要使用代理以地址开头的服务器)。显然,这不是一个好的解决方案,因为通常没有人在此处列出这些字符串(第一个复选框对于非 Java 应用程序就足够了)。

第二个(微不足道的)解决方案只是在我的代码段中计算这些字符串,即使 JVM 不这么认为,也不要为它们使用代理设置。我认为这不是一个好的解决方案,如果这是唯一的解决方案,恕我直言,JVM 存在缺陷。

我在 Internet 上找到了许多资源如何学习系统代理设置。但是如何学习非代理设置呢?

谢谢,PP

public static final String HTTP_PROXY_HOST_KEY = "http.proxyHost";
public static final String HTTPS_PROXY_HOST_KEY = "https.proxyHost";
public static final String HTTP_PROXY_PORT_KEY = "http.proxyPort";
public static final String HTTPS_PROXY_PORT_KEY = "https.proxyPort";
public static final String NO_PROXY_HOSTS_KEY = "http.nonProxyHosts";

// provide list of urls which are to be accessed by this application and return proxy and non-proxy settings
private Properties getSystemProxyConfiguration(String[] urls) {
    log.debug("Getting system proxy");
    Properties properties = new Properties();
    SortedSet<String> nonProxyHosts = new TreeSet<>();
    for (String url : urls) {
        URI uri;
        try {
            uri = new URI(url);
        } catch (URISyntaxException e) {
            throw new IllegalStateException(e);
        }
        InetSocketAddress address = getSystemProxy(uri);
        if (address != null) {
            if (url.toLowerCase().startsWith("https")) {
                properties.put(HTTPS_PROXY_HOST_KEY, address.getHostString());
                properties.put(HTTPS_PROXY_PORT_KEY, ""+address.getPort());
                //todo verify that all previous URLs in this array are using the same proxy
                log.debug("HTTPS proxy: " + address.getHostString() + ":" + address.getPort());
            } else {
                properties.put(HTTP_PROXY_HOST_KEY, address.getHostString());
                properties.put(HTTP_PROXY_PORT_KEY, ""+address.getPort());
                //todo verify that all previous URLs in this array are using the same proxy
                log.debug("HTTP proxy: " + address.getHostString() + ":" + address.getPort());
            }
        } else {  //todo DEFECT -> this does not find the non-proxy hosts (even though specified in IE Internet settings)
            nonProxyHosts.add(uri.getHost());
        }
    }
    if (nonProxyHosts.size() > 0) {
        String nonProxyHostsString = nonProxyHosts.first();
        nonProxyHosts.remove(nonProxyHostsString);
        for (String nonProxyHost : nonProxyHosts) {
            nonProxyHostsString = nonProxyHostsString + "|" + nonProxyHost;
        }
        properties.put(NO_PROXY_HOSTS_KEY, nonProxyHostsString);
        log.debug("Non HTTP(S) proxy hosts: "+nonProxyHostsString);
    } else {
        log.debug("No non HTTP(S) proxy hosts set");
    }
    return properties;
}

private InetSocketAddress getSystemProxy(URI uri) {
    List<Proxy> proxyList;
    proxyList = ProxySelector.getDefault().select(uri);
    if (proxyList != null && proxyList.size() > 0) { //todo DEFECT - this never returns DIRECT proxy for localhost, 127.0.0.1, my-computer-name strings
        Proxy proxy = proxyList.get(0);
        if (proxyList.size() > 1) {
            log.warn("There is more " + proxy.type() + " proxies available. Use "+PROXY_PROPERTIES_FILE_NAME+" to set the right one.");
        }
        InetSocketAddress address = (InetSocketAddress) proxy.address();
        return address;
    }
    return null;
}
4

0 回答 0