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