内部接口@FeignClient使用@ReqeustMapping并实现Fallback
背景:
在编写内部接口时,有同事在interface
上用了@RequestMapping("/xxx")
注解,然后在@FeignClient
注解中使用了fallback
,并实现了接口的fallback
类,导致启动时报错:
Caused by: java.lang.IllegalStateException: Ambiguous mapping. Cannot map 'com.xxx.xxx.core.fegin.OrganizationRoleIntApi' method
com.xxx.xxx.core.fegin.OrganizationRoleIntApi#detail(String)
to {GET /organ_role_api/detail}: There is already 'organizationRoleIntFallback' bean method
com.xxx.xxx.core.fegin.rollback.OrganizationRoleIntFallback#detail(String) mapped.
at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping$MappingRegistry.validateMethodMapping(AbstractHandlerMethodMapping.java:636) ~[spring-webmvc-5.2.6.RELEASE.jar:5.2.6.RELEASE]
at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping$MappingRegistry.register(AbstractHandlerMethodMapping.java:603) ~[spring-webmvc-5.2.6.RELEASE.jar:5.2.6.RELEASE]
at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.registerHandlerMethod(AbstractHandlerMethodMapping.java:318) ~[spring-webmvc-5.2.6.RELEASE.jar:5.2.6.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping.registerHandlerMethod(RequestMappingHandlerMapping.java:377) ~[spring-webmvc-5.2.6.RELEASE.jar:5.2.6.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping.registerHandlerMethod(RequestMappingHandlerMapping.java:74) ~[spring-webmvc-5.2.6.RELEASE.jar:5.2.6.RELEASE]
at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.lambda$detectHandlerMethods$1(AbstractHandlerMethodMapping.java:288) ~[spring-webmvc-5.2.6.RELEASE.jar:5.2.6.RELEASE]
at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping$$Lambda$955/1611272816.accept(Unknown Source) ~[na:na]
产生原因:
在服务启动时,Spring
会扫描带有@RequestMapping
注解的类,实现路由注册,处理@RequestMapping
类为AbstractHandlerMethodMapping<T>
,注册方法为org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.MappingRegistry#register
,其中mappingLookup
是用来缓存路由的,每次在缓存之前先会做校验,调用校验方法org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.MappingRegistry#validateMethodMapping
根据key值查询mappingLookup
中是否已经缓存了路由信息,如果缓存了,则直接抛出异常,如果没有缓存,则返回之后将路由信息缓存值mappingLookup
中。
具体代码:
register
:
validateMethodMapping
:
解决方案:
- 如果用要用
@FeignClient
的fallback
实现熔断兜底处理,那么就不能在interface
上用@RequestMapping
注解,在interface
中定义统一公共路由前缀即可。- 如果要用
@FeignClient
的fallbackFactory
实现熔断兜底处理,那么interface上的@RequestMapping
注解就没有影响了,利用FallbackFactory<T>
实现匿名内部类中各个方法的兜底处理。