是否有一种方法可以在使用SpringCloud OpenFeign的同时为每个Feign实例创建不同的客户端?<



我们可以在使用OpenFeign时为Feign实例指定客户端,如下所示:

his.fooClient = Feign.builder()
.client(clientA)
.target(FooClient.class, "https://PROD-SVC");
this.adminClient = Feign.builder()
.client(clientB)
.target(FooClient.class, "https://PROD-SVC");

但是,如果使用SpringCloud OpenFeign,似乎没有办法这样做,所有Feign实例将共享一个客户端,因为我们无法根据文档为Feign实例配置客户端:https://docs.spring.io/spring-cloud-openfeign/docs/current/reference/html/appendix.html.

那么我如何在使用SpringCloud OpenFeign时实现这个目标呢?

您必须手动创建Feign实例,与使用OpenFeign的方式相同。

好消息是,您可以将SpringCloud OpenFeign的部分配置与@Import({FeignClientsConfiguration.class})一起使用

@RefreshScope也可以与这种方法一起使用。对于使用@FeignClient注释创建的客户端,无法使用@RefreshScope

对于简单的情况,可以使用FeignClientBuilder。但是配置Feign的能力很差。


这些bean将从FeignClientsConfiguration导入:
Decoder,Encoder,Contract,FeignLoggerFactory

Contract用于使用Spring REST注释,如@PostMapping

@Component
@RefreshScope
@Import({FeignClientsConfiguration.class})
class SomeClientFeign implements SomeClientApi {
private static final boolean ALWAYS_FOLLOW_REDIRECTS = true;
private final SomeConfig config;
private final Decoder decoder;
private final Encoder encoder;
private final Contract contract;
private final FeignLoggerFactory loggerFactory;
private SomeClientApi clientApi;
@Autowired
public SomeClientFeign(SomeConfig config,
Decoder decoder, Encoder encoder,
Contract contract, FeignLoggerFactory loggerFactory) {
this.config = config;
this.decoder = decoder;
this.encoder = encoder;
this.contract = contract;
this.loggerFactory = loggerFactory;
}
@PostConstruct
private void createFeignClient() {
Logger logger = loggerFactory.create(SomeClientApi.class);
Logger.Level logLevel = config.isLogging() ? Logger.Level.FULL : Logger.Level.NONE;
clientApi = Feign.builder()
.client(client())
.retryer(Retryer.NEVER_RETRY)
.logger(logger)
.logLevel(logLevel)
.encoder(encoder).decoder(decoder).contract(contract)
.options(requestOptions())
.requestInterceptor(basicAuthRequestInterceptor())
.target(SomeClientApi.class, config.getUrl());
}
private OkHttpClient client() {
// to not recreate the client for each request, it is not important because the same dispatcher is used
okhttp3.OkHttpClient client = new okhttp3.OkHttpClient.Builder()
.connectTimeout(config.getConnectTimeoutMillis(), TimeUnit.MILLISECONDS)
.readTimeout(config.getReadTimeoutMillis(), TimeUnit.MILLISECONDS)
.followRedirects(ALWAYS_FOLLOW_REDIRECTS)
.build();
return new OkHttpClient(client);
}
private Request.Options requestOptions() {
return new Request.Options(
config.getConnectTimeoutMillis(), TimeUnit.MILLISECONDS,
config.getReadTimeoutMillis(), TimeUnit.MILLISECONDS,
ALWAYS_FOLLOW_REDIRECTS
);
}
private BasicAuthRequestInterceptor basicAuthRequestInterceptor() {
return new BasicAuthRequestInterceptor(config.getUsername(), config.getPassword());
}
@Override
public SomeResponse create(SomeRequest request) {
return clientApi.createSomething(request);
}
}

相关内容

  • 没有找到相关文章

最新更新