我正在编写要在 Windows 上运行的 Java (1.7) 应用程序。该应用程序正在访问在同一主机上运行的其他服务以及在Internet 中运行的其他服务。应用程序可以运行在两种环境中,一种是必须指定代理设置(访问互联网时有代理);而在其他环境中,则不得指定代理设置(没有代理)。
我希望应用程序简单,并且不希望其用户为 cmd 行(-Dhttp.proxyHost 等)上的代理设置规范而烦恼 - 应用程序应该从 Windows 系统设置(IE / 工具)中学习代理设置/ Internet 属性 / 连接 / LAN 设置)。
我已经编写了一段应该学习该设置的代码,见下文。问题是这段代码没有将localhost、127.0.0.1和my-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;
}