SpringCloud : 多个 @FeignClient 注解 value 设置为同一个应用的解决方案

Feign 版本10.1.0

Spring 版本 5.1.5.RELEASE

SpringBoot 版本 2.1.5.RELEASE

SpringCloud 版本 2.1.1.RELEASE

在微服务架构中,当我们需要进行服务间调用时可以选择feign组件,

现在遇到的问题是: 当同一个服务,声明多个feign实例时,启动时直接报错。

解决办法,通过 Feign.builder() 手动生成代理类。 另一种见评论区:#允许bean实例同名覆盖allow-bean-definition-overriding: true

1.定义接口:

2.配置接口代理

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson.support.config.FastJsonConfig;
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
import com.alibaba.fastjson.support.springfox.SwaggerJsonSerializer;
import com.netflix.appinfo.InstanceInfo;
import com.netflix.discovery.EurekaClient;
import com.yunplus.bpg.cloud.file.proxy.client.QcloudClient;
import com.yunplus.bpg.cloud.file.proxy.client.TaskClient;
import feign.Contract;
import feign.Feign;
import feign.codec.Decoder;
import feign.codec.Encoder;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
import org.springframework.cloud.openfeign.FeignContext;
import org.springframework.cloud.openfeign.support.SpringDecoder;
import org.springframework.cloud.openfeign.support.SpringEncoder;
import org.springframework.http.MediaType;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;

/**
 * Feign配置类,负责实例化所需要的伪客户端
 */
@Component
public class RemoteXxxClient {

    public final static String SERVICE_ID = "XXX-SERVICE-ID";

    /**
     * FeignClientFactoryBean 该工厂类中 设置builder属性时就是通过该对象,源码中可看到
     */
    protected FeignContext feignContext;

    /**
     * 通过注入Eureka实例对象,就不用手动指定url,只需要指定服务名即可
     */
    protected EurekaClient eurekaClient;

    private static final Map FEIGN_CLIENTS = new ConcurrentHashMap<>();

    @Autowired
    public void init(final EurekaClient eurekaClient, final FeignContext feignContext) {
        this.eurekaClient = eurekaClient;
        this.feignContext = feignContext;
    }

    @Bean
    public AbcClient getQcloudService() {
        return create(AbcClient.class, SERVICE_ID);
    }

    @Bean
    public DefClient getTaskService() {
        return create(DefClient.class, SERVICE_ID);
    }

    /**
     * 设置编码解码器为FastJson
     *
     * @param clazz
     * @param serverId
     * @param
     * @return
     */
    protected  T create(Class clazz, String serverId) {
        InstanceInfo nextServerFromEureka = eurekaClient.getNextServerFromEureka(serverId, false);
        String key = nextServerFromEureka.getIPAddr() + ":" + nextServerFromEureka.getPort() + ":" + clazz.getName();
        Object object = FEIGN_CLIENTS.get(key);
        if (Objects.isNull(object)) {
            object = Feign.builder()
                //encoder指定对象编码方式
                .encoder(this.feignEncoder())
                //decoder指定对象解码方式
                .decoder(this.feignDecoder())
                //.client(feignClient)
                //options方法指定连接超时时长及响应超时时长
                .options(new Request.Options(5000, 5000))
                //retryer方法指定重试策略
                //.retryer(new Retryer.Default(5000, 5000, 3))
                .contract(feignContext.getInstance(serverId, Contract.class))
                //target方法绑定接口与服务端地址。返回类型为绑定的接口类型。
                .target(clazz, nextServerFromEureka.getHomePageUrl());
            FEIGN_CLIENTS.put(key, object);
        }

        return (T) object;
    }

    protected Encoder feignEncoder() {
        return new SpringEncoder(feignHttpMessageConverter());
    }

    protected Decoder feignDecoder() {
        return new SpringDecoder(feignHttpMessageConverter());
    }

    /**
     * 设置解码器为fastjson
     *
     * @return
     */
    private ObjectFactory feignHttpMessageConverter() {
        final HttpMessageConverters httpMessageConverters = new HttpMessageConverters(this.getFastJsonConverter());
        return () -> httpMessageConverters;
    }

    private FastJsonHttpMessageConverter getFastJsonConverter() {
        FastJsonHttpMessageConverter converter =
                new FastJsonHttpMessageConverter();

        List supportedMediaTypes = new ArrayList<>();
        MediaType mediaTypeJson =
                MediaType.valueOf(MediaType.APPLICATION_JSON_UTF8_VALUE);
        supportedMediaTypes.add(mediaTypeJson);
        converter.setSupportedMediaTypes(supportedMediaTypes);
        FastJsonConfig config = new FastJsonConfig();
        config.getSerializeConfig().put(JSON.class, new SwaggerJsonSerializer());
        config.setSerializerFeatures(SerializerFeature.DisableCircularReferenceDetect);
        converter.setFastJsonConfig(config);

        return converter;
    }
}

3.调用

PS:

Original: https://www.cnblogs.com/phpdragon/p/12119128.html
Author: phpdragon
Title: SpringCloud : 多个 @FeignClient 注解 value 设置为同一个应用的解决方案

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/541334/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • 003-博学谷-年度钻石C++/C-Unix/Linux(2)

    常用命令 3.1 概述 很多人可能在电视或电影中看到过类似的场景,黑客面对一个黑色的屏幕,上面飘着密密麻麻的字符,梆梆一顿敲,就完成了窃取资料的任务。 Linux 刚出世时没有什么…

    Java 2023年6月7日
    0130
  • git 常用命令

    来时绿叶阑珊,愿走时鲜花绽开。。。。。。不经意间的指尖流沙岁月透微笑,伤心处静坐溪水泪潸然,人生就两个字:”如梦”。 git clone git://git…

    Java 2023年6月16日
    086
  • spring security登录认证流程

    spring security登录认证流程 1、前端携带用户名和面膜发送请求,controller接收到后,调用service的login方法 2、根据传过来的用户名和密码生成Us…

    Java 2023年6月9日
    082
  • 熊大同学的面试回忆录(2.5年开发经验)

    今天去看牙医,他问我年级轻轻牙齿怎么磨损这么严重?我说,没有点赞的这些年,我都是咬着牙过来的。 以下为读者面试后的分享,部分回答笔者做了一些补充整理,希望对你有帮助。(两年左右开发…

    Java 2023年5月29日
    077
  • Java中装饰者模式

    装饰模式可以在不改变原来类中代码的基础上,增强类中的方法 装饰类LDHWrapper和被装饰类LDH必须实现同个接口Star 装饰类中要定义属性为:被装饰类对象,同时定义构造方法 …

    Java 2023年6月15日
    082
  • 基于springframework框架的不同网络请求request方式传参

    一、get方式 1.在url路径上传递参数,形如 /getTask/{taskId} 如/getTask/111 2.在url后面以?形式传递参数,形如/getTask?taskI…

    Java 2023年5月30日
    087
  • 聊聊redis的主从复制吧

    聊聊基础概念 主从复制与主从替换 主从复制不同于主从替换,主从复制是正常情况下主节点同步数据到从节点;主从替换是主节点挂了之后,把从节点替换为主节点; 从节点存在的意义:备份主节点…

    Java 2023年6月8日
    089
  • 浅谈 Golang 插件机制

    我们知道类似 Java 等半编译半解释型语言编译生成的都是类似中间态的字节码,所以在 Java 里面我们想要实现程序工作的动态扩展,可以通过 Java 的字节码编辑技术([[动态代…

    Java 2023年6月7日
    086
  • 使用Animate.css

    Animate.css是一个css动画库,可以做出一些非常好看的动画; 官网:https://animate.style Animate.css非常容易上手,但是动画是一开始就加载…

    Java 2023年6月6日
    0112
  • 微信扫码登录

    微信登录之前还需要了解OAuth2知识 前期准备 注册微信开放平台 邮箱激活 完善开发者资料(暂不支持个体用户) 开发者资质认证: &#x8425;&#x4E1A;…

    Java 2023年6月13日
    0103
  • 数组目标值target两个整数,并返回它们的数组下标

    1、题目背景 给定一个整数数组nums和一个整数目标值target,请你在该数组中找出和为目标值target的那两个整数,并返回它们的数组下标。 你可以假设每种输入只会对应一个答案…

    Java 2023年6月8日
    095
  • Java-Collection、Map和Array之间的转换

    设个User类: public class User { private String userName; private String userId; private Strin…

    Java 2023年6月8日
    089
  • IDEA必备插件

    一、插件入口 二、IDEA必备插件 插件安装目录:C:\Users\用户名\AppData\Roaming\JetBrains\IntelliJIdea2021.3\plugins…

    Java 2023年6月8日
    063
  • 2、oracle安装出现的问题

    1、问题:scott用户在安装时未解锁的问题 方案: 2、适配器错误 方案:确保勾选的服务是启动状态 3、 posted @2022-09-23 17:09 红酒人生 阅读(46 …

    Java 2023年6月13日
    092
  • 分布式文件存储–FastDFS

    上传交互过程 client询问tracker上传到的storage,不需要附加参数; tracker返回一台可用的storage; client直接和storage通讯完成文件上传…

    Java 2023年5月29日
    084
  • 【Python】使用Selenium实现淘宝抢单

    最近,小明为了达成小姐姐的愿望,在某宝买到心仪的宝贝,再加上又迷上了python,就通过python轻而易举地实现了(个人声明:对Java来说,这并不是背叛)。 需求分析&…

    Java 2023年6月13日
    0103
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球