有没有办法在使用 SpringCloud OpenFeign 时为每个 Feign 实例创建不同的客户端?

Posted

技术标签:

【中文标题】有没有办法在使用 SpringCloud OpenFeign 时为每个 Feign 实例创建不同的客户端?【英文标题】:Is there a way to create different client for each Feign instance while using SpringCloud OpenFeign? 【发布时间】:2021-05-11 04:19:37 【问题描述】:

我们可以在使用 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 时如何实现该目标?

【问题讨论】:

SC OpenFeign 正在配置一个客户端。您所描述的场景将是一项新功能。 【参考方案1】:

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

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

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

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

这些 bean 将从 FeignClientsConfiguration 导入:DecoderEncoderContractFeignLoggerFactory

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);
    


【讨论】:

以上是关于有没有办法在使用 SpringCloud OpenFeign 时为每个 Feign 实例创建不同的客户端?的主要内容,如果未能解决你的问题,请参考以下文章

springcloud 整合openFeign

SpringCloud上传文件,经过Zuul,中文文件名乱码解决办法

开源技术路线是不是不好用?有没有什么解决办法?

有没有人使用过嵌入在 .NET 桌面应用程序中的 Open Office?

cobbler 无人值守安装出现 PXE-E32:TFTP OPen timeout的解决办法

SpringCloud+Feign环境下文件上传与form-data同时存在的解决办法