RestTemplate 使用代理的几种方式

参照 golang http 库使用代理的方式,是在创建 http client 的时候进行设置代理。这里也是同样的,可以对 http client 设置代理

Java 与 goland 相对应的系统层面的设置代理的变量


http.proxyHost: the host name of the proxy server
http.proxyPort: the port number, the default value being 80.
http.nonProxyHosts:a list of hosts that should be reached directly, bypassing the proxy. This is a list of patterns separated by '|'. The patterns may start or end with a '*' for wildcards. Any host matching one of these patterns will be reached through a direct connection instead of through a proxy.

The https (http over SSL) protocol handler has its own set of properties:

https.proxyHost
https.proxyPort

使用方法示例一
java -Dhttp.proxyHost=webcache.example.com -Dhttp.proxyPort=8080 -Dhttp.nonProxyHosts=”localhost|host.example.com” GetURL

使用方法示例二

Socket socket = new Socket(Proxy.NO_PROXY);
socket.connect(new InetAddress("localhost", 1234));

Java 使用代码设置代理

Java官方文档根据不同的协议设置代理并移除失效代理示例

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

public class MyProxySelector extends ProxySelector {
        // Keep a reference on the previous default
    ProxySelector defsel = null;
        
        /*
         * Inner class representing a Proxy and a few extra data
         */
        class InnerProxy {
        Proxy proxy;
                SocketAddress addr;
                // How many times did we fail to reach this proxy?
                int failedCount = 0;
                
                InnerProxy(InetSocketAddress a) {
                        addr = a;
                        proxy = new Proxy(Proxy.Type.HTTP, a);
                }
                
                SocketAddress address() {
                        return addr;
                }
                
                Proxy toProxy() {
                        return proxy;
                }
                
                int failed() {
                        return ++failedCount;
                }
        }
        
        /*
         * A list of proxies, indexed by their address.
         */
        HashMap<SocketAddress, InnerProxy> proxies = new HashMap<SocketAddress, InnerProxy>();

        MyProxySelector(ProxySelector def) {
          // Save the previous default
          defsel = def;
          
          // Populate the HashMap (List of proxies)
          InnerProxy i = new InnerProxy(new InetSocketAddress("webcache1.example.com", 8080));
          proxies.put(i.address(), i);
          i = new InnerProxy(new InetSocketAddress("webcache2.example.com", 8080));
          proxies.put(i.address(), i);
          i = new InnerProxy(new InetSocketAddress("webcache3.example.com", 8080));
          proxies.put(i.address(), i);
          }
          
          /*
           * This is the method that the handlers will call.
           * Returns a List of proxy.
           */
          public java.util.List<Proxy> select(URI uri) {
                // Let's stick to the specs. 
                if (uri == null) {
                        throw new IllegalArgumentException("URI can't be null.");
                }
                
                /*
                 * If it's a http (or https) URL, then we use our own
                 * list.
                 */
                String protocol = uri.getScheme();
                if ("http".equalsIgnoreCase(protocol) ||
                        "https".equalsIgnoreCase(protocol)) {
                        ArrayList<Proxy> l = new ArrayList<Proxy>();
                        for (InnerProxy p : proxies.values()) {
                          l.add(p.toProxy());
                        }
                        return l;
                }
                
                /*
                 * Not HTTP or HTTPS (could be SOCKS or FTP)
                 * defer to the default selector.
                 */
                if (defsel != null) {
                        return defsel.select(uri);
                } else {
                        ArrayList<Proxy> l = new ArrayList<Proxy>();
                        l.add(Proxy.NO_PROXY);
                        return l;
                }
        }
        
        /*
         * Method called by the handlers when it failed to connect
         * to one of the proxies returned by select().
         */
        public void connectFailed(URI uri, SocketAddress sa, IOException ioe) {
                // Let's stick to the specs again.
                if (uri == null || sa == null || ioe == null) {
                        throw new IllegalArgumentException("Arguments can't be null.");
                }
                
                /*
                 * Let's lookup for the proxy 
                 */
                InnerProxy p = proxies.get(sa); 
                        if (p != null) {
                                /*
                                 * It's one of ours, if it failed more than 3 times
                                 * let's remove it from the list.
                                 */
                                if (p.failed() >= 3)
                                        proxies.remove(sa);
                        } else {
                                /*
                                 * Not one of ours, let's delegate to the default.
                                 */
                                if (defsel != null)
                                  defsel.connectFailed(uri, sa, ioe);
                        }
     }
}

RestTemplate 使用代理

  1. 给 http client 配置代理,并按目标地址使用不同的代理, 使用 setRoutePlanner() 示例
		<dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpcore</artifactId>
            <version>4.4.10</version>
        </dependency>
        <dependency>
            <groupId>commons-httpclient</groupId>
            <artifactId>commons-httpclient</artifactId>
            <version>3.1</version>
        </dependency>
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
            <version>4.5.6</version>
        </dependency>
@Slf4j
@Configuration
public class RestTemplateConfig {


    private String httpsProxyHost;
    private int httpsProxyPort;
    private String targetBaseUrl;

    @Bean
    RestTemplate restTemplate() throws KeyStoreException, NoSuchAlgorithmException, KeyManagementException, URIException {
        HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory();
        requestFactory.setConnectionRequestTimeout(5000);
        requestFactory.setConnectTimeout(10000);
        requestFactory.setReadTimeout(5000);

        HttpHost proxy = new HttpHost(httpsProxyHost, httpsProxyPort);
        URI targetURI = new URI(targetBaseUrl, false);
        String targetHost = targetURI.getHost();
        log.info("targetURI = {}, targetHost = {}", targetURI, targetHost);

        SSLContextBuilder builder = new SSLContextBuilder();
        builder.loadTrustMaterial(null, (X509Certificate[] x509Certificates, String s) -> true);
        SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(builder.build(), new String[]{"SSLv2Hello", "SSLv3", "TLSv1", "TLSv1.2"}, null, NoopHostnameVerifier.INSTANCE);
        Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
                .register("http", new PlainConnectionSocketFactory())
                .register("https", socketFactory).build();
        PoolingHttpClientConnectionManager poolingHttpClientConnectionManager = new PoolingHttpClientConnectionManager(registry);
        poolingHttpClientConnectionManager.setMaxTotal(200);
        CloseableHttpClient httpClient = HttpClients.custom().setSSLSocketFactory(socketFactory)
                .setConnectionManager(poolingHttpClientConnectionManager)
                .setConnectionManagerShared(true)
                .setRoutePlanner(new DefaultProxyRoutePlanner(proxy) {
                    @Override
                    protected HttpHost determineProxy(HttpHost target, HttpRequest request, HttpContext context) throws HttpException {
                        log.info("target host name = {}", target.getHostName());
                        if (target.getHostName().equals(targetHost)) {
                            return super.determineProxy(target, request, context);
                        }
                        return null;
                    }
                })
                .build();

        requestFactory.setHttpClient(httpClient);
        RestTemplate restTemplate = new RestTemplate(requestFactory);

        List<HttpMessageConverter<?>> converterList = new ArrayList<>();
        converterList.add(new MappingJackson2HttpMessageConverter());
        converterList.add(new StringHttpMessageConverter(Charset.forName("UTF-8")));
        restTemplate.setErrorHandler(new DefaultResponseErrorHandler());
        restTemplate.setMessageConverters(converterList);

        return restTemplate;
    }

}
  1. 既按协议又按目标地址,使用 ProxySelector 示例

https://stackoverflow.com/questions/34319679/using-proxy-with-httpcomponentsclienthttprequestfactory-and-resttemplate

HttpRoutePlanner routePlanner = new SystemDefaultRoutePlanner(new MyProxySelector());

HttpComponentsClientHttpRequestFactory clientHttpRequestFactory 
    = new HttpComponentsClientHttpRequestFactory(
        HttpClientBuilder.create()
            .setRoutePlanner(routePlanner)
            .build());
restTemplate = new RestTemplate(clientHttpRequestFactory);
package hello;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.net.Proxy.Type;
import java.net.ProxySelector;
import java.net.SocketAddress;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;

public class MyProxySelector extends ProxySelector {

    ProxySelector defaultproxySelector = ProxySelector.getDefault();

    ArrayList<Proxy> noProxy = new ArrayList<Proxy>();
    ArrayList<Proxy> secureProxy = new ArrayList<Proxy>();
    ArrayList<Proxy> sociaMediaProxy = new ArrayList<Proxy>();

    public MyProxySelector(){

        noProxy.add(Proxy.NO_PROXY);

        secureProxy.add(new Proxy(Type.HTTP, new InetSocketAddress(
            "secure.proxy.mycompany.com", 8080)));

        sociaMediaProxy.add(new Proxy(Type.HTTP, new InetSocketAddress(
                "social-media.proxy.mycompany.com", 8080)));
    }

    @Override
    public List<Proxy> select(URI uri) {

        // No proxy for local company addresses.
        if ( uri.getHost().toLowerCase().endsWith("mycompany.com") ) {
            return noProxy ;
        }

        // Special proxy for social networks.
        String host = uri.getHost().toLowerCase();
        if (    host.endsWith("facebook.com") ||
                host.endsWith("twitter.com") ||
                host.endsWith("cfapps.io") ||               
                host.endsWith("flickr.com") ) 
        {
            return sociaMediaProxy ;
        }

        // for https URIs use secureProxy
        if ( uri.getScheme().toLowerCase().equals("https") ){
            return secureProxy ;
        }

        if (defaultproxySelector != null) {
            return defaultproxySelector.select(uri);
        }

        return noProxy;
    }

    @Override
    public void connectFailed(URI arg0, SocketAddress arg1, IOException arg2) {
        // TODO Auto-generated method stub
    }
}
  1. 需要用户名密码的场景
    Spring RestTemplate with proxy settings and proxy authentication
    @PostConstruct
    public void init() {
        this.restTemplate = new RestTemplate();

        final int proxyPortNum = Integer.parseInt(proxyPort);
        final CredentialsProvider credsProvider = new BasicCredentialsProvider();
        credsProvider.setCredentials(new AuthScope(proxyHost, proxyPortNum), new UsernamePasswordCredentials(proxyUser, proxyPassword));

        final HttpClientBuilder clientBuilder = HttpClientBuilder.create();
        clientBuilder.useSystemProperties();
        clientBuilder.setProxy(new HttpHost(proxyHost, proxyPortNum));
        clientBuilder.setDefaultCredentialsProvider(credsProvider);
        clientBuilder.setProxyAuthenticationStrategy(new ProxyAuthenticationStrategy());
        final CloseableHttpClient client = clientBuilder.build();

        final HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory();
        factory.setHttpClient(client);

        restTemplate.setRequestFactory(factory);
    }

Ref

https://docs.oracle.com/javase/8/docs/technotes/guides/net/proxies.html

https://howtodoinjava.com/spring-boot2/resttemplate/resttemplate-get-example/

https://stackoverflow.com/questions/64025199/resttemplate-with-proxy-how-to-test

https://www.baeldung.com/java-resttemplate-proxy

https://stackoverflow.com/questions/3687670/using-resttemplate-how-to-send-the-request-to-a-proxy-first-so-i-can-use-my-jun?rq=4

https://stackoverflow.com/questions/44821561/how-to-set-proxy-host-on-httpclient-request-in-java

https://stackoverflow.com/questions/34319679/using-proxy-with-httpcomponentsclienthttprequestfactory-and-resttemplate

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值