参照 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 使用代理
- 给 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;
}
}
- 既按协议又按目标地址,使用
ProxySelector
示例
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
}
}
@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