SpringCloud micro service calls, more @FeignClient annotation value set to the same class of service solutions

In the micro-service architecture, when we need to choose between service calls can feign components,

Problems encountered now is: when the same service, declare more than feign instance, the direct error at startup.

 

Solutions generated proxy class manually by Feign.builder ().

1. Definition Interface:

 

public interface AbcClient{
    @ResponseBody
    @PostMapping("/abc")
    JSONObject doSomething(@RequestBody Req request);
}

public interface DefClient{
    @ResponseBody
    @PostMapping("/def")
    JSONObject doSomething(@RequestBody Req request);
}

 

 

2. Configure interface agent

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.stereotype.Component;

Import of java.util.ArrayList;
 Import java.util.List; 

/ ** 
 * Feign configuration class is responsible for instantiating the desired pseudo client 
 * / 
@Component 
public  class RemoteXxxClient { 

    public  Final  static String SERVICE_ID = "XXX-Service- ID " ; 

    / ** 
     * FeignClientFactoryBean the plant builder class attributes provided by that object is, the source can be seen in 
     * / protected FeignContext feignContext; 

    / ** 
     * Eureka instance by injecting the object, do not have to manually specify url, requires only you can specify the service name 
     * / protected EurekaClient eurekaClient; 

    Private  static  Final the Map <String, Object> = FEIGN_CLIENTS new new ConcurrentHashMap <>();

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

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

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

    /**
     * 设置编码解码器为FastJson
     *
     * @param clazz
     * @param serverId
     * @param <T>
     * @return
     */
    protected <T> T create(Class<T> clazz, String serverId) {
        InstanceInfo nextServerFromEureka = eurekaClient.getNextServerFromEureka(serverId, false);
        Object object = FEIGN_CLIENTS.get(nextServerFromEureka.getIPAddr());
        if (Objects.isNull(object)) {
            object = Feign.builder()
                    //encoder指定对象编码方式
                    .encoder(the this.feignEncoder ())
                     // Decoder decoding scheme specified object 
                    .decoder ( the this .feignDecoder ()) 
                    .client (feignClient) 
                    // Options connection method specified length and response timeout period timeout 
                    .options ( new new Request.Options (5000, 5000 ) )
                     // retryer method specified retry strategy
                     // .retryer (new new Retryer.Default (5000, 5000, 3)) 
                    .contract (feignContext.getInstance (serverId, Contract. class ))
                     // target method to bind the interface with the server address. Return type of interface type binding. 
                    .target (clazz, nextServerFromEureka.getHomePageUrl ()) ;
            FEIGN_CLIENTS.put(nextServerFromEureka.getIPAddr(), object);
        }

        return (T) object;
    }

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

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

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

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

        List<MediaType> 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. Call

@Slf4j
@Service
public class MyLogic {

    @Autowired
    private AbcClient abcClient;
    
    public void callDownstreamService() {
        Req req = new Req();
        JSONObject rsp = abcClient.doSomething(req);
    }
}

 

PS:

https://blog.csdn.net/neosmith/article/details/82349449

https://blog.csdn.net/zaige66/article/details/86507929

 

Guess you like

Origin www.cnblogs.com/phpdragon/p/12119128.html