代理选择器:每个 URL 的不同代理



我试图了解ProxySelector类是如何工作的。我当前的代码如下所示:

    URI uri = new URI("http://google.com");
    proxySelector.select(uri);

我知道在调用proxySelector.select(uri);时,这应该返回相应 URI 的代理列表。但是我不知道如何为每个URI设置代理。

我知道我可以使用setDefault()方法设置默认代理,但据我了解,这将设置系统范围的代理,而不是特定URI的代理。

我可能在这里错过了一些基本点,但是如何为 url A 设置一个代理(例如 http://google.com)和为 url B 设置一个不同的代理(例如 http://ebay.com),然后让系统每次连接到相应的 url 时自动选择正确的代理?

  1. 重写ProxySelector.select(URI uri)实现自定义逻辑的方法,以便为 URI 选择正确的代理或代理列表。

  2. 通过调用 ProxySelector.setDefault(customProxySelector) 将新的、自定义的ProxySelector设置为系统范围。

    URLConnection的任何子类都将使用ProxySelector,例如:

    URLConnection conn = url.openConnection();
    
  3. 或配置您将用于调用远程 URI 的框架,例如 Spring RestTemplate:

    HttpRoutePlanner routePlanner = new SystemDefaultRoutePlanner(new MyProxySelector());
    HttpComponentsClientHttpRequestFactory clientHttpRequestFactory 
        = new HttpComponentsClientHttpRequestFactory(
            HttpClientBuilder.create()
                .setRoutePlanner(routePlanner)
                .build());
    restTemplate = new RestTemplate(clientHttpRequestFactory);
    

最好在自定义select(URI uri)中回退到默认代理选择器,以防自定义逻辑无法确定 uri 的合适代理。

请参阅我对代理选择器示例的另一个答案。

网络和代理在 Java 网络和代理(第 4 段 ProxySelector)和 ProxySelector Java 文档中有很好的解释。

实际上,只需使用增强的ProxySelector,即可很好地工作而无需任何反射,该ProxySelector支持特定URL的白名单,并将其余部分传递给委托(又名默认)ProxySelector。

public class DelegatingProxySelector extends ProxySelector {
    private final Set<URI> allProxiedUri = new HashSet<>();
    private String proxyHost;
    private Integer proxyPort;
    private final ProxySelector delegate;
    public DelegatingProxySelector(
        String proxyHost, Integer proxyPort, ProxySelector delegate) {
        this.proxyHost = proxyHost;
        this.proxyPort = proxyPort;
        this.delegate = delegate;
    }
    @Override
    public List<Proxy> select(final URI uri) {
        if (allProxiedUri.contains(uri)) {
            final InetSocketAddress proxyAddress = InetSocketAddress
                .createUnresolved(proxyHost, proxyPort);
            return Collections.singletonList(new Proxy(Type.HTTP, proxyAddress));
        }
        return delegate.select(uri);
    }
    @Override
    public void connectFailed(final URI uri, final SocketAddress sa, final IOException ioe) {
        System.err.println("Unable to reach uri " + uri + " via proxy: " + ioe.getMessage());
    }
    
    public void addProxiedUri(URI uri) {
        allProxiedUri.add(uri);
    }
}

final DelegatingProxySelector delegatingProxySelector = new DelegatingProxySelector("localhost", 3128, ProxySelector.getDefault());
ProxySelector.setDefault(delegatingProxySelector);

最新更新