在 Feign 上配置代理路由规划器
我需要知道如何使用 Spring Boot REST 客户端在代理服务器后面发出请求。我可以使用 apache commons 对于 REST 请求进行此配置,如下所示:
执行POST的方法:
Map <String, Object> map = new TreeMap <String, Object> ();
DynamicProxyRoutePlanner routePlanner = getProxy (param);
CloseableHttpClient closeableHttpClient = HttpClients.custom (). SetRoutePlanner (routePlanner) .build ();
GetProxy 方法:
private DynamicProxyRoutePlanner getProxy (Map <Integer, Object> param) {
HttpHost proxy = new HttpHost ((String) param.get (PROXY), (Integer) param.get (PROXY_PORT));
DynamicProxyRoutePlanner routePlanner = new DynamicProxyRoutePlanner (proxy);
return routePlanner;
}
DynamicProxyRoutePlanner 类:
public class DynamicProxyRoutePlanner implements HttpRoutePlanner {
private DefaultProxyRoutePlanner defaultProxyRoutePlanner = null;
public DynamicProxyRoutePlanner (HttpHost host) {
defaultProxyRoutePlanner = new DefaultProxyRoutePlanner (host);
}
public void setProxy (HttpHost host) {
defaultProxyRoutePlanner = new DefaultProxyRoutePlanner (host);
}
public HttpRoute determineRoute (HttpHost target, HttpRequest request, HttpContext context) throws HttpException {
return defaultProxyRoutePlanner.determineRoute (target, request, context);
}
}
总结...
已编辑--
我创建了一个类
@Configuration
public class FeignConfiguration {
用方法
@Bean
@ConditionalOnMissingBean (CloseableHttpClient.class)
public CloseableHttpClient httpClient () {
DynamicProxyRoutePlanner routePlanner = getProxy ();
CredentialsProvider credentialsProvider = getCredentials ();
return HttpClients.custom ()
.setDefaultCredentialsProvider (credentialsProvider)
.setRoutePlanner (routePlanner) .build ();
}
private DynamicProxyRoutePlanner getProxy () {
HttpHost proxy = new HttpHost (HOST_PROXY, PORT_PROXY);
return new DynamicProxyRoutePlanner (proxy);
}
public CredentialsProvider getCredentials () {
AuthCache authCache = new BasicAuthCache ();
CredentialsProvider credsProvider = new BasicCredentialsProvider ();
credsProvider.setCredentials (new AuthScope (HOST_PROXY, PORT_PROXY, AuthScope.ANY_HOST, "ntlm"),
new NTCredentials (USER, PASS, "", DOMAIN));
HttpClientContext context = HttpClientContext.create ();
context.setCredentialsProvider (credsProvider);
context.setAuthCache (authCache);
return credsProvider;
}
我已经重新安装了连接测试,但即使 Feign 似乎没有尝试使用代理设置,请参阅以下错误:
2018-04-25 09: 59: 10.494 ERROR 25309 --- [nio-9063-exec-2] oaccC [. [. [.] [DispatcherServlet]: Servlet.service () for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is feign.RetryableException: Connection refused (Connection refused) executing POST http://sinaflor-api.des.basis.com.br/api/empreendimentos] with root cause
java.net.ConnectException: Connection refused (Connection refused)
at java.net.PlainSocketImpl.socketConnect (Native Method) ~ [na: 1.8.0_171]
at java.net.AbstractPlainSocketImpl.doConnect (AbstractPlainSocketImpl.java:350) ~ [na: 1.8.0_171]
at java.net.AbstractPlainSocketImpl.connectToAddress (AbstractPlainSocketImpl.java:206) ~ [na: 1.8.0_171]
at java.net.AbstractPlainSocketImpl.connect (AbstractPlainSocketImpl.java:188) ~ [na: 1.8.0_171]
at java.net.SocksSocketImpl.connect (SocksSocketImpl.java:392) ~ [na: 1.8.0_171]
at java.net.Socket.connect (Socket.java:589) ~ [na: 1.8.0_171]
at sun.net.NetworkClient.doConnect (NetworkClient.java:175) ~ [na: 1.8.0_171]
at sun.net.www.http.HttpClient.openServer (HttpClient.java:463) ~ [na: 1.8.0_171]
at sun.net.www.http.HttpClient.openServer (HttpClient.java:558) ~ [na: 1.8.0_171]
at sun.net.www.http.HttpClient. <init> (HttpClient.java:242) ~ [na: 1.8.0_171]
at sun.net.www.http.HttpClient.New (HttpClient.java:339) ~ [na: 1.8.0_171]
at sun.net.www.http.HttpClient.New (HttpClient.java:357) ~ [na: 1.8.0_171]
at sun.net.www.protocol.http.HttpURLConnection.getNewHttpClient (HttpURLConnection.java:1220) ~ [na: 1.8.0_171]
at sun.net.www.protocol.http.HttpURLConnection.plainConnect0 (HttpURLConnection.java:1156) ~ [na: 1.8.0_171]
at sun.net.www.protocol.http.HttpURLConnection.plainConnect (HttpURLConnection.java:1050) ~ [na: 1.8.0_171]
at sun.net.www.protocol.http.HttpURLConnection.connect (HttpURLConnection.java:984) ~ [na: 1.8.0_171]
at sun.net.www.protocol.http.HttpURLConnection.getOutputStream0 (HttpURLConnection.java:1334) ~ [na: 1.8.0_171]
at sun.net.www.protocol.http.HttpURLConnection.getOutputStream (HttpURLConnection.java:1309) ~ [na: 1.8.0_171]
at feign.Client $ Default.convertAndSend (Client.java:133) ~ [feign-core-9.3.1.jar: na]
at feign.Client $ Default.execute (Client.java:73) ~ [feign-core-9.3.1.jar: na]
at feign.SynchronousMethodHandler.executeAndDecode (SynchronousMethodHandler.java:97) ~ [feign-core-9.3.1.jar: na]
at feign.SynchronousMethodHandler.invoke (SynchronousMethodHandler.java:76) ~ [feign-core-9.3.1.jar: na]
at feign.ReflectiveFeign $ FeignInvocationHandler.invoke (ReflectiveFeign.java:103) ~ [feign-core-9.3.1.jar: na]
at com.sun.proxy $ Proxy112.send (Unknown Source) ~ [na: na]
我能够使用 okHttpClient 解析 feign 中的代理配置,如下所示:
@Configuration
public class FeignConfigurationProxy {
@Value("${url.proxy_host}")
private String HOST_PROXY;
@Value("${url.proxy_port}")
private Integer PORT_PROXY;
private OkHttpClient okHttpClient;
private Proxy proxy;
@PostConstruct
public void init() {
buildProxy();
buildOkHttpClient();
}
@Bean(name = "feign")
public Feign buildClient() {
return Feign.builder().client(new feign.okhttp.OkHttpClient(okHttpClient)).build();
}
@Bean(name = "okhttpclient")
public OkHttpClient okHttpClient() {
return okHttpClient;
}
public void buildOkHttpClient() {
buildProxy();
okHttpClient = new OkHttpClient.Builder().proxy(proxy).build();
}
public void buildProxy() {
proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(HOST_PROXY, PORT_PROXY));
}
}
在 pom.xml 中我添加了依赖项:
<dependency>
<groupId> io.github.openfeign </ groupId>
<artifactId> feign-okhttp </ artifactId>
<version> 9.5.0 </ version>
</ dependency>
<dependency>
<groupId> com.squareup.okhttp3 </ groupId>
<artifactId> okhttp </ artifactId>
<version> 3.10.0 </ version>
</ dependency>
Spring cloud openfeign 支持三种底层实现:
根据您的项目中使用的实现方式,以下是如何配置 feign 客户端以使用 HTTP 代理: 技巧:配置 feign 客户端,然后在 Spring 应用程序上下文中覆盖默认客户端 bean。
默认:
import feign.Client;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.net.InetSocketAddress;
import java.net.Proxy;
@Configuration
public class FeignConfiguration {
...
@Bean
public Client feignClient() {
return new Client.Proxied(null, null,
new Proxy(Proxy.Type.HTTP,
new InetSocketAddress(proxyHost, proxyPort)));
}
}
使用 ApacheHttpClient:
使用 OkHttpClient:当您的
或feign.httpclient.enabled: true
中包含application.yml
及以下内容时:pom.xml
build.gradle
当您的
pom.xml <dependency> <groupId>io.github.openfeign</groupId> <artifactId>feign-httpclient</artifactId> </dependency> build.gradle implementation 'io.github.openfeign:feign-httpclient' import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClientBuilder; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.apache.http.HttpHost; @Configuration public class FeignConfiguration { ... @Bean public CloseableHttpClient feignClient() { return HttpClientBuilder.create().setProxy( new HttpHost(proxyHost, proxyPort)).build(); } }
或
中包含feign.okhttp.enabled: true
及以下内容时:application.yml
pom.xml
只需将您的
build.gradle
从 Spring Cloud
Edgware版本开始,如果您将
pom.xml
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-okhttp</artifactId>
</dependency>
build.gradle
implementation 'io.github.openfeign:feign-okhttp'
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.net.InetSocketAddress;
import java.net.Proxy;
import okhttp3.OkHttpClient;
@Configuration
public class FeignConfiguration {
...
@Bean
public OkHttpClient okHttpClient() {
return new OkHttpClient.Builder()
.proxy(new Proxy(Proxy.Type.HTTP,
new InetSocketAddress(proxyHost, proxyPort)))
.build();
}
}
定义为 Spring Bean,则将使用它而不是默认的
在我的案例中使用代理隧道到另一个网址
CloseableHttpClient