缓存java http代理设置,直到JVM重新启动

时间:2011-11-10 11:10:18

标签: java http

我正在尝试在我的用户界面(在Java 1.6.0.23上运行的Eclipse应用程序)中更改JVM的代理设置

if (isUseProxy()) {
    System.setProperty("java.net.useSystemProxies", "true");
    System.setProperty("http.proxyHost", getProxyHost());
    System.setProperty("http.proxyPort", getProxyPort());
    System.setProperty("https.proxyHost", getProxyHost());
    System.setProperty("https.proxyPort", getProxyPort());
    ..........
} else {
    System.clearProperty("http.proxyHost");
    System.clearProperty("http.proxyPort");
    System.clearProperty("https.proxyHost");
    System.clearProperty("https.proxyPort");
}

问题是在JVM重新启动之前不会使用新的代理服务器值,它会在Java中缓存。

Java版:

java.runtime.version=1.6.0_26-b03
java.specification.name=Java Platform API Specification
java.specification.vendor=Sun Microsystems Inc.

更新: 魔术继续...我试图隔离问题,以弄清楚Java如何神奇地与system.properties一起工作。 看起来Java在某些随机情况下会忽略无效的代理服务器设置。此测试失败:

import org.junit.Test;

import java.io.IOException;
import java.net.*;

import static org.junit.Assert.fail;

public class ProxySetTest {

  @Test
  public void verifyProxyIsNotCachedInJVM() throws IOException {

    tryConnectionToGoogleCom();

    System.setProperty("http.proxyHost", getInvalidProxyHost());
    System.setProperty("http.proxyPort", getInvalidProxyPort()+"");
    System.setProperty("https.proxyHost", getInvalidProxyHost());
    System.setProperty("https.proxyPort", getInvalidProxyPort()+"");

    // Next connection will be through the invalid proxy. must fail?
    try {
      tryConnectionToGoogleCom();
      fail("must have failed with an exception because of invalid proxy setting");
    } catch (Exception e) {
      System.out.println("received exception: " + e);
    }

    // clear the proxy setting and try connecting again - must succeed
    System.clearProperty("http.proxyHost");
    System.clearProperty("http.proxyPort");
    System.clearProperty("https.proxyHost");
    System.clearProperty("https.proxyPort");

    // and without proxy again
    tryConnectionToGoogleCom();
  }

  private void tryConnectionToGoogleCom() throws IOException {
    URL url = new URL("http://google.com");
    HttpURLConnection connection = (HttpURLConnection) url.openConnection();
    connection.connect();
  }

  private int getInvalidProxyPort() {
    return 1234;
  }

  private String getInvalidProxyHost() {
    return "asd";
  }
}

3 个答案:

答案 0 :(得分:6)

所以我遇到了完全相同的问题,并将其跟踪到轴缓存信息。

位于org.apache.axis.components.net.TransportClientPropertiesFactory

有问题的方法是:

public static TransportClientProperties create(String protocol)
{
    TransportClientProperties tcp =
        (TransportClientProperties)cache.get(protocol);

    if (tcp == null) {
        tcp = (TransportClientProperties)
            AxisProperties.newInstance(TransportClientProperties.class,
                                       (Class)defaults.get(protocol));

        if (tcp != null) {
            cache.put(protocol, tcp);
        }
    }

    return tcp;
}

在第一次调用时,将使用代理的当前JVM设置创建tcp对象。在后续调用中,它会提取缓存版本,因此即使您更改了JVM中的代理设置,也无关紧要。想看看我是否能找到清除缓存的方法。

答案 1 :(得分:2)

package com.alskor;

import org.junit.Test;

import java.io.IOException;
import java.net.*;

import static org.junit.Assert.fail;

public class ProxySetTest {

  @Test
  public void verifyProxyIsNotCachedInJVM() throws IOException {

    tryConnectionToGoogleCom();

    ProxySelector savedSelector = ProxySelector.getDefault();
    java.net.ProxySelector.setDefault(new FixedProxySelector(getInvalidProxyHost(), getInvalidProxyPort()));

    // Next connection will be through the invalid proxy. must fail?
    try {
      tryConnectionToGoogleCom();
      fail("must have failed with an exception because of invalid proxy setting");
    } catch (Exception e) {
      System.out.println("received exception: " + e);
    }

    // clear the proxy setting and try connecting again - must succeed
    java.net.ProxySelector.setDefault(savedSelector);
    // and without proxy again
    tryConnectionToGoogleCom();
  }

  private void tryConnectionToGoogleCom() throws IOException {
    URL url = new URL("http://google.com");
    HttpURLConnection connection = (HttpURLConnection) url.openConnection();
    connection.connect();
  }

  private int getInvalidProxyPort() {
    return 1234;
  }

  private String getInvalidProxyHost() {
    return "asd";
  }
}

package com.alskor;

import sun.misc.RegexpPool;

import java.io.IOException;
import java.net.*;
import java.util.ArrayList;
import java.util.List;

public class FixedProxySelector extends ProxySelector {

  private final String host;
  private final int port;

  public FixedProxySelector(String host, int port) {
    this.host = host;
    this.port = port;
  }

  @Override
  public java.util.List<Proxy> select(URI uri) {
    if (uri == null) {
      throw new IllegalArgumentException("URI can't be null.");
    }
    List<Proxy> proxies = new ArrayList<Proxy>();
    SocketAddress addr = new InetSocketAddress(host, port);
    proxies.add(new Proxy(Proxy.Type.SOCKS, addr));
    proxies.add(new Proxy(Proxy.Type.HTTP, addr));

    return proxies;
  }

  @Override
  public void connectFailed(URI uri, SocketAddress sa, IOException ioe) {
    if (uri == null || sa == null || ioe == null) {
      throw new IllegalArgumentException("Arguments can't be null.");
    }
    throw new RuntimeException(ioe.toString(), ioe);
  }

}

答案 2 :(得分:1)

将java.net.Proxy对象传递给URL.openConnection(代理)方法。 您可以使用Proxy.NO_PROXY进行直接连接。或者像这样创建新的代理:

new Proxy(Proxy.Type.HTTP, new InetSocketAddress("localhost", 8080))

以下是完整的示例:

public class TestConnectOverProxy {

  static class Connector {
    private Proxy proxy = Proxy.NO_PROXY;

    public void setProxy(Proxy proxy) {
      this.proxy = proxy;
    }

    /**
     * This method works with java.net.Proxy field of the Connector class
     * as described
     * <a href="http://www.rgagnon.com/javadetails/java-0085.html">here</a>
     */
    public String getContent(URL url) throws IOException {
      HttpURLConnection conn = (HttpURLConnection) url.openConnection(proxy);
      conn.connect();
      System.out.println(conn.getRequestMethod());
      System.out.println(conn.getResponseCode());
      return IOUtils.toString(conn.getInputStream());
    }
  }

  @Test
  public void test() throws IOException {
    URL url = new URL("http://www.google.com");
    Connector connector = new Connector();


    //connect directly
    connector.setProxy(Proxy.NO_PROXY);
    System.out.println(connector.getContent(url));

    //connect over proxy
    connector.setProxy(new Proxy(Proxy.Type.HTTP, new InetSocketAddress("localhost", 8080)));
    System.out.println(connector.getContent(url));
  }
}