正文
Feign
是声明性的web服务客户端。它使编写web服务客户端更加容易。通过Feign我们可以实现调用远程服务像调用本地一样便捷。本篇文章主要详细聊聊Feign
下的一个核心注解@FeignClient
相关属性。
通过查阅@FeignClient源码,可以看到它的注解包括以下属性:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | @Target ({ElementType.TYPE}) @Retention (RetentionPolicy.RUNTIME) @Documented public @interface FeignClient { @AliasFor ( "name" ) String value() default "" ; /** @deprecated */ @Deprecated String serviceId() default "" ; String contextId() default "" ; @AliasFor ( "value" ) String name() default "" ; String qualifier() default "" ; String url() default "" ; boolean decode404() default false ; Class>[] configuration() default {}; Class> fallback() default void . class ; Class> fallbackFactory() default void . class ; String path() default "" ; boolean primary() default true ; } |
name
定义当前客户端Client的名称,等同于value
属性。
value
定义当前客户端Client的名称,等同于name
属性。
serviceId
目前serviceId
已经废弃了,直接使用name即可。
contextId
比如我们有个user
服务,但user
服务中有很多个接口,我们不想将所有的调用接口都定义在一个类中,比如UserFeignClientA
、UserFeignClentB
,当不同的Feign
的name
一致的时候,这时候Bean
的名称就会冲突,解决方式可以通过指定不同的contextId
来解决问题,举个栗子:
UserFeignClientA
1 2 3 4 5 6 7 8 | @FeignClient (name = "user.service" , contextId = "userServiceA" , url = "${user.service.url}" , configuration = UserRemoteConfig. class ) public interface UserFeignClientA { /** * 获取用户默认身份信息 */ @RequestMapping ( "/user/identity/default" ) ResultData getDefaultIdentity( @RequestParam ( "userId" ) String userId); } |
UserFeignClientB
1 2 3 4 5 6 7 8 | @FeignClient (name = "user.service" , contextId = "userServiceB" url = "${user.service.url}" , configuration = UserRemoteConfig. class ) public interface UserFeignClientB { /** * 新增大客户信息 */ @RequestMapping (value = { "/user/identity/saveIdentity" }, method = RequestMethod.POST) ResultData saveIdentity( @RequestBody UserVisaIdentity userVisaIdentity); } |
url
url
用于配置指定服务的地址,相当于直接请求这个服务。
path
1 2 3 4 5 6 7 8 9 10 11 | @FeignClient (name = "template-service" , url = "${universal.service.url}" , path = "template" , configuration = {RemoteErrorDecoder. class }) public interface ITemplateFeignService { /** * 多条件查询 * * @param templateSearchDto 多条件查询 * @return 模板列表 */ @GetMapping ( "/search" ) ApiResult> search( @Valid @SpringQueryMap TemplateSearchDto templateSearchDto); } |
path
定义当前FeignClient
访问接口时的统一前缀,比如接口地址是/user/get, 如果你定义了前缀是user, 那么具体方法上的路径就只需要写/get 即可。上面将假设universal.service.url
地址为 http://universal.com
,那么调用search
请求地址为:universal.com/template/se…
configuration
configuration
是配置Feign
配置类,在配置类中可以自定义Feign
的Encoder
、Decoder
、LogLevel
、Contract
等。
fallback
fallback
定义容错的处理类,也就是回退逻辑,fallback
的类必须实现Feign Client
的接口,无法知道熔断的异常信息。比如:
1 2 3 4 5 6 7 8 9 10 11 12 13 | @FeignClient (name = "account-service" ) public interface AccountServiceClient { @RequestMapping (method = RequestMethod.GET, value = "/accounts/{accountName}" , consumes = MediaType.APPLICATION_JSON_UTF8_VALUE, fallback = AccountServiceClientFallback. class ) String getAccount( @PathVariable ( "accountName" ) String accountName); } @Component public class AccountServiceClientFallback implements AccountServiceClient { private static final Logger LOGGER = LoggerFactory.getLogger(AccountServiceClientFallback. class ); @Override public String getAccount(String accountName) { LOGGER.error( "Error during getAccount, accountName: {}" , accountName); } } |
fallbackFactory
也是容错的处理,可以知道熔断的异常信息。可以自定义fallbackFactory
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | @Component public class UserRemoteClientFallbackFactory implements FallbackFactory { private Logger logger = LoggerFactory.getLogger(UserRemoteClientFallbackFactory. class ); @Override public UserRemoteClient create(Throwable cause) { return new UserRemoteClient() { @Override public User getUser( int id) { logger.error( "UserRemoteClient.getUser异常" , cause); return new User( 0 , "默认" ); } }; } } @FeignClient (value = "user-service" , fallbackFactory = UserRemoteClientFallbackFactory. class ) public interface UserRemoteClient { @GetMapping ( "/user/get" ) public User getUser( @RequestParam ( "id" ) int id); } |
primary
primary
对应的是@Primary
注解,默认为true
,官方这样设置也是有原因的。当我们的Feign
实现了fallback
后,也就意味着FeignClient
有多个相同的Bean
在Spring
容器中,当我们在使用@Autowired
进行注入的时候,不知道注入哪个,所以我们需要设置一个优先级高的,@Primary
注解就是干这件事情的。
qualifier
qualifier
对应的是@Qualifier
注解,使用场景跟上面的primary
关系很淡,一般场景直接@Autowired直接注入就可以了。
如果我们的Feign Client
有fallback
实现,默认@FeignClient
注解的primary=true
, 意味着我们使用@Autowired
注入是没有问题的,会优先注入你的FeignClient
。
如果你把primary
设置成false
了,直接用@Autowired
注入的地方就会报错,不知道要注入哪个对象。
解决方案很明显,你可以将primary
设置成true
即可,如果由于某些特殊原因,你必须得去掉primary=true
的设置,这种情况下我们怎么进行注入,我们可以配置一个qualifier
,然后使用@Qualifier
注解进行注入,示列如下:
1 2 3 4 5 | @FeignClient (name = "optimization-user" , path= "user" , qualifier= "userRemoteClient" ) public interface UserRemoteClient { @GetMapping ( "/get" ) public User getUser( @RequestParam ( "id" ) int id); } |
Feign Client注入
1 2 3 | @Autowired @Qualifier ( "userRemoteClient" ) private UserRemoteClient userRemoteClient; |
好了,以上就是@FeignClient注解相关属性说明。
以上就是远程调用@FeignClient注解属性使用详解的详细内容,更多关于@FeignClient 远程调用的资料请关注IT俱乐部其它相关文章!