做网站推广价格,怎么在国外建网站,江西省工程建设网站,有和wind一样做用网站FeignClient介绍
FeignClient 是 Spring Cloud 中用于声明一个 Feign 客户端的注解。由于SpringCloud采用分布式微服务架构#xff0c;难免在各个子模块下存在模块方法互相调用的情况。比如订单服务要调用库存服务的方法#xff0c;FeignClient()注解就是为了解决这个问题的…FeignClient介绍
FeignClient 是 Spring Cloud 中用于声明一个 Feign 客户端的注解。由于SpringCloud采用分布式微服务架构难免在各个子模块下存在模块方法互相调用的情况。比如订单服务要调用库存服务的方法FeignClient()注解就是为了解决这个问题的。
Feign 是一个声明式的 Web Service 客户端它的目的是让编写 HTTP 客户端变得更简单。通过 Feign只需要创建一个接口并使用注解来描述请求就可以直接执行 HTTP 请求了。
FeignClient()注解的源码要求它必须在Interface接口上使用 FeignClient注解被Target(ElementType.TYPE)修饰表示FeignClient注解的作用目标在接口上
SpringBoot服务的启动类必须要有EnableFeignClients 注解才能使FeginClient注解生效。
FeignClient工作原理及整体流程
Feign服务调用的工作原理可以总结为以下几个步骤
首先通过EnableFeignCleints注解开启FeignCleint。根据Feign的规则实现接口添加FeignCleint注解。程序启动后会扫描所有有FeignCleint的类并将这些信息注入到ioc容器中。注入时从FeignClientFactoryBean.class获取FeignClient。当接口的方法被调用时通过jdk的代理来生成具体的RequesTemplateRequesTemplate生成http的Request。Request交给Client去处理其中Client可以是HttpUrlConnection、HttpClient也可以是Okhttp。Client被封装到LoadBalanceClient类这个类结合类Ribbon做到了负载均衡。
整体流程
FeignClient常用属性
name、value
指定FeignClient的名称如果项目使用了Ribbonname属性会作为微服务的名称用于服务发现 这两个属性的作用是一样的如果没有配置url那么配置的值将作为服务的名称用于服务的发现反之只是一个名称。
FeignClient(name order-server)
public interface OrderRemoteClient {GetMapping(/order/detail)public Order detail(RequestParam(orderId) String orderId);
}注意
这里写的是你要调用的那个服务的名称spring.application.name属性配置而不是你自己的那个服务的名称。如果同一个工程中出现两个接口使用一样的服务名称会报错。原因是Client名字注册到容器中重复了。除非指定不同的contextId参数。 Description: The bean ‘order-server.FeignClientSpecification’, defined in null, could not be registered. A bean with that name has already been defined in null and overriding is disabled. Action: Consider renaming one of the beans or enabling overriding by setting spring.main.allow-bean-definition-overridingtrue
两种解决方案
增加配置 spring.main.allow-bean-definition-overridingtrue为每个FeignClient手动指定不同的contextId
contextId
比如我们有个user服务但user服务中有很多个接口我们不想将所有的调用接口都定义在一个类中那就可以给不同的client指定contextId不然就会报Consider renaming one of the beans or enabling overriding by setting spring.main.allow-bean-definition-overridingtrue异常。 注意contextId不能带_等符号。
FeignClient(name order-server)
public interface OrderRemoteClient {GetMapping(/api/order/detail, contextId OrderRemoteClient)public Order detail(RequestParam(orderId) String orderId);
}上面给出了Bean名称冲突后的解决方案下面来分析下contextId在Feign Client的作用在注册Feign Client Configuration的时候需要一个名称名称是通过getClientName方法获取的
String name getClientName(attributes);registerClientConfiguration(registry, name,
attributes.get(configuration));private String getClientName(MapString, Object client) {if (client null) {return null;}String value (String) client.get(contextId);if (!StringUtils.hasText(value)) {value (String) client.get(value);}if (!StringUtils.hasText(value)) {value (String) client.get(name);}if (!StringUtils.hasText(value)) {value (String) client.get(serviceId);}if (StringUtils.hasText(value)) {return value;}throw new IllegalStateException(Either name or value must be provided in FeignClient.class.getSimpleName());}可以看到如果配置了contextId就会用contextId如果没有配置就会去value然后是name最后是serviceId。默认都没有配置当出现一个服务有多个Feign Client的时候就会报错了。
其次的作用是在注册FeignClient中contextId会作为Client 别名的一部分如果配置了qualifier优先用qualifier作为别名。
private void registerFeignClient(BeanDefinitionRegistry registry,AnnotationMetadata annotationMetadata, MapString, Object attributes) {String className annotationMetadata.getClassName();BeanDefinitionBuilder definition BeanDefinitionBuilder.genericBeanDefinition(FeignClientFactoryBean.class);validate(attributes);definition.addPropertyValue(url, getUrl(attributes));definition.addPropertyValue(path, getPath(attributes));String name getName(attributes);definition.addPropertyValue(name, name);String contextId getContextId(attributes);definition.addPropertyValue(contextId, contextId);definition.addPropertyValue(type, className);definition.addPropertyValue(decode404, attributes.get(decode404));definition.addPropertyValue(fallback, attributes.get(fallback));definition.addPropertyValue(fallbackFactory, attributes.get(fallbackFactory));definition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE);// 拼接别名String alias contextId FeignClient;AbstractBeanDefinition beanDefinition definition.getBeanDefinition();boolean primary (Boolean) attributes.get(primary); // has a default, wont be nullbeanDefinition.setPrimary(primary);// 配置了qualifier优先用qualifierString qualifier getQualifier(attributes);if (StringUtils.hasText(qualifier)) {alias qualifier;}BeanDefinitionHolder holder new BeanDefinitionHolder(beanDefinition, className,new String[] { alias });BeanDefinitionReaderUtils.registerBeanDefinition(holder, registry);}
url
url用于配置指定服务的地址相当于直接请求这个服务。像调试等场景可以使用。
FeignClient(name order-server, url http://localhost:8085)
public interface OrderRemoteClient {GetMapping(/api/order/detail)public Order detail(RequestParam(orderId) String orderId);
}path
path定义当前FeignClient访问接口时的统一前缀。 比如接口地址是/order/detail, 如果你定义了前缀是order, 那么具体方法上的路径就只需要写/detail即可。
FeignClient(name order-server, url http://localhost:8085, path /api/order)
public interface OrderRemoteClient {GetMapping(/detail)public Order detail(RequestParam(orderId) String orderId);
}primary
primary对应的是Primary注解默认为true官方这样设置也是有原因的。当我们的Feign实现了fallback后也就意味着Feign Client有多个相同的Bean在Spring容器中当我们在使用Autowired进行注入的时候不知道注入哪个所以我们需要设置一个优先级高的Primary注解就是干这件事情的。
qualifier
qualifier对应的是Qualifier注解使用场景跟上面的primary关系很淡一般场景直接Autowired直接注入就可以了。
如果我们的Feign Client有fallback实现默认FeignClient注解的primarytrue, 意味着我们使用Autowired注入是没有问题的会优先注入你的Feign Client。
如果你鬼斧神差的把primary设置成false了直接用Autowired注入的地方就会报错不知道要注入哪个对象。
解决方案很明显你可以将primary设置成true即可如果由于某些特殊原因你必须得去掉primarytrue的设置这种情况下我们怎么进行注入我们可以配置一个qualifier然后使用Qualifier注解进行注入。 Feign Client 定义
FeignClient(name order-server, path /api/order, qualifierorderRemoteClient)
public interface OrderRemoteClient {GetMapping(/detail)public Order detail(RequestParam(orderId) String orderId);
}Feign Client注入
Autowired
Qualifier(orderRemoteClient)
private OrderRemoteClient orderRemoteClient;configuration
configuration是配置Feign配置类在配置类中可以自定义Feign的Encoder、Decoder、LogLevel、Contract等。
configuration定义
public class FeignConfiguration {Beanpublic Logger.Level getLoggerLevel() {return Logger.Level.FULL;}Beanpublic BasicAuthRequestInterceptor basicAuthRequestInterceptor() {return new BasicAuthRequestInterceptor(user, password);}Beanpublic CustomRequestInterceptor customRequestInterceptor() {return new CustomRequestInterceptor();}// Contract,feignDecoder,feignEncoder.....
}使用示列
FeignClient(value order-server, configuration FeignConfiguration.class)
public interface OrderRemoteClient {GetMapping(/api/order/detail)public Order detail(RequestParam(orderId) String orderId);}fallback
定义容错的处理类也就是回退逻辑当调用远程接口失败或超时时会调用对应接口的容错逻辑fallback指定的类必须实现FeignClient标记的接口无法知道熔断的异常信息。
fallback定义
Component
public class OrderRemoteClientFallback implements OrderRemoteClient {Overridepublic Order detail(String orderId) {return new Order(order-998, 默认fallback);}}使用示列
FeignClient(value order-server, fallback OrderRemoteClientFallback.class)
public interface OrderRemoteClient {GetMapping(/api/order/detail)public Order detail(RequestParam(orderId) String orderId);}fallbackFactory
也是容错的处理可以知道熔断的异常信息。工厂类用于生成fallback类示例通过这个属性我们可以实现每个接口通用的容错逻辑减少重复的代码。
fallbackFactory定义
Component
public class OrderRemoteClientFallbackFactory implements FallbackFactoryOrderRemoteClient {private Logger logger LoggerFactory.getLogger(OrderRemoteClientFallbackFactory.class);Overridepublic OrderRemoteClient create(Throwable cause) {return new OrderRemoteClient() {Overridepublic Order detail(String id) {logger.error(OrderRemoteClient.detail 异常, cause);return new Order(order-998, 默认);}};}
}使用示列
FeignClient(value order-server, fallbackFactory OrderRemoteClientFallbackFactory.class)
public interface OrderRemoteClient {GetMapping(/order/detail)public Order detail(RequestParam(orderId) String orderId);}FeignClient添加Header信息
在RequestMapping中添加
FeignClient(url ${orderServer_domain:http://order:8082},value order-server,contextId OrderServerClient,path /api/order)
public interface OrderRemoteClient {RequestMapping(value/detail, method RequestMethod.POST,headers {Content-Typeapplication/json;charsetUTF-8})Order detail(RequestParam(orderId) String orderId);
}使用RequestHeader注解添加
FeignClient(url ${orderServer_domain:http://order:8082},value order-server,contextId OrderServerClient,path /api/order)
public interface OrderRemoteClient {RequestMapping(value/detail, method RequestMethod.POST)ListString detail(RequestHeader MapString, String headerMap, RequestParam(orderId) String orderId);
}使用Headers注解添加
FeignClient(url ${orderServer_domain:http://order:8082},value order-server,contextId OrderServerClient,path /api/order)
public interface OrderRemoteClient {RequestMapping(value/detail, method RequestMethod.POST)Headers({Content-Type: application/json;charsetUTF-8})ListString detail(RequestHeader MapString, String headerMap, RequestParam(orderId) String orderId);
}实现RequestInterceptor接口
Configuration
public class FeignRequestInterceptor implements RequestInterceptor {Overridepublic void apply(RequestTemplate temp) {temp.header(HttpHeaders.AUTHORIZATION, XXXXX);}}FeignClient 源码
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//package org.springframework.cloud.openfeign;import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.core.annotation.AliasFor;Target({ElementType.TYPE})
Retention(RetentionPolicy.RUNTIME)
Documented
Inherited
public interface FeignClient {AliasFor(name)String value() default ;String contextId() default ;AliasFor(value)String name() default ;String[] qualifiers() default {};String url() default ;boolean dismiss404() default false;Class?[] configuration() default {};Class? fallback() default void.class;Class? fallbackFactory() default void.class;String path() default ;boolean primary() default true;
} 文章转载自: http://www.morning.mttqp.cn.gov.cn.mttqp.cn http://www.morning.hylbz.cn.gov.cn.hylbz.cn http://www.morning.gbnsq.cn.gov.cn.gbnsq.cn http://www.morning.kchwr.cn.gov.cn.kchwr.cn http://www.morning.qpljg.cn.gov.cn.qpljg.cn http://www.morning.ktlfb.cn.gov.cn.ktlfb.cn http://www.morning.hmgqy.cn.gov.cn.hmgqy.cn http://www.morning.kpqjr.cn.gov.cn.kpqjr.cn http://www.morning.pclgj.cn.gov.cn.pclgj.cn http://www.morning.rfbq.cn.gov.cn.rfbq.cn http://www.morning.ybhrb.cn.gov.cn.ybhrb.cn http://www.morning.rcjqgy.com.gov.cn.rcjqgy.com http://www.morning.trplf.cn.gov.cn.trplf.cn http://www.morning.mprpx.cn.gov.cn.mprpx.cn http://www.morning.hhpbj.cn.gov.cn.hhpbj.cn http://www.morning.jcwhk.cn.gov.cn.jcwhk.cn http://www.morning.ltpmy.cn.gov.cn.ltpmy.cn http://www.morning.yxzfl.cn.gov.cn.yxzfl.cn http://www.morning.srgsb.cn.gov.cn.srgsb.cn http://www.morning.xqbbc.cn.gov.cn.xqbbc.cn http://www.morning.fjptn.cn.gov.cn.fjptn.cn http://www.morning.qxkjy.cn.gov.cn.qxkjy.cn http://www.morning.kzhxy.cn.gov.cn.kzhxy.cn http://www.morning.grxyx.cn.gov.cn.grxyx.cn http://www.morning.hngmg.cn.gov.cn.hngmg.cn http://www.morning.dxpqd.cn.gov.cn.dxpqd.cn http://www.morning.xiaobaixinyong.cn.gov.cn.xiaobaixinyong.cn http://www.morning.qklff.cn.gov.cn.qklff.cn http://www.morning.qlznd.cn.gov.cn.qlznd.cn http://www.morning.kpbn.cn.gov.cn.kpbn.cn http://www.morning.jtsdk.cn.gov.cn.jtsdk.cn http://www.morning.swimstaracademy.cn.gov.cn.swimstaracademy.cn http://www.morning.cbvlus.cn.gov.cn.cbvlus.cn http://www.morning.fhjnh.cn.gov.cn.fhjnh.cn http://www.morning.nxkyr.cn.gov.cn.nxkyr.cn http://www.morning.blqmn.cn.gov.cn.blqmn.cn http://www.morning.spfh.cn.gov.cn.spfh.cn http://www.morning.tmbtm.cn.gov.cn.tmbtm.cn http://www.morning.qnywy.cn.gov.cn.qnywy.cn http://www.morning.czzpm.cn.gov.cn.czzpm.cn http://www.morning.jrlxz.cn.gov.cn.jrlxz.cn http://www.morning.fhhry.cn.gov.cn.fhhry.cn http://www.morning.rahllp.com.gov.cn.rahllp.com http://www.morning.wyjpt.cn.gov.cn.wyjpt.cn http://www.morning.czwed.com.gov.cn.czwed.com http://www.morning.hcsnk.cn.gov.cn.hcsnk.cn http://www.morning.pxrfm.cn.gov.cn.pxrfm.cn http://www.morning.shnqh.cn.gov.cn.shnqh.cn http://www.morning.ftznb.cn.gov.cn.ftznb.cn http://www.morning.krjyq.cn.gov.cn.krjyq.cn http://www.morning.csnch.cn.gov.cn.csnch.cn http://www.morning.gidmag.com.gov.cn.gidmag.com http://www.morning.qhjkz.cn.gov.cn.qhjkz.cn http://www.morning.qxmnf.cn.gov.cn.qxmnf.cn http://www.morning.ywrt.cn.gov.cn.ywrt.cn http://www.morning.mlycx.cn.gov.cn.mlycx.cn http://www.morning.gslz.com.cn.gov.cn.gslz.com.cn http://www.morning.knjj.cn.gov.cn.knjj.cn http://www.morning.hbywj.cn.gov.cn.hbywj.cn http://www.morning.fkffr.cn.gov.cn.fkffr.cn http://www.morning.fllfc.cn.gov.cn.fllfc.cn http://www.morning.rlqwz.cn.gov.cn.rlqwz.cn http://www.morning.kjksn.cn.gov.cn.kjksn.cn http://www.morning.wmgjq.cn.gov.cn.wmgjq.cn http://www.morning.glncb.cn.gov.cn.glncb.cn http://www.morning.cbnlg.cn.gov.cn.cbnlg.cn http://www.morning.rhsg.cn.gov.cn.rhsg.cn http://www.morning.ywzqk.cn.gov.cn.ywzqk.cn http://www.morning.yydeq.cn.gov.cn.yydeq.cn http://www.morning.ndyrb.com.gov.cn.ndyrb.com http://www.morning.rqkzh.cn.gov.cn.rqkzh.cn http://www.morning.jcrlx.cn.gov.cn.jcrlx.cn http://www.morning.cyjjp.cn.gov.cn.cyjjp.cn http://www.morning.tfrmx.cn.gov.cn.tfrmx.cn http://www.morning.qblcm.cn.gov.cn.qblcm.cn http://www.morning.qbfqb.cn.gov.cn.qbfqb.cn http://www.morning.hffpy.cn.gov.cn.hffpy.cn http://www.morning.jpbpc.cn.gov.cn.jpbpc.cn http://www.morning.gxtbn.cn.gov.cn.gxtbn.cn http://www.morning.chfxz.cn.gov.cn.chfxz.cn