feign 接口不能多重继承问题 Only single-level inheritance supported

9 篇文章 0 订阅
1 篇文章 0 订阅

feign.Contract.BaseContract.parseAndValidatateMetadata
抛出的异常, 代码如下:

if (targetType.getInterfaces().length == 1) {
	Util.checkState(targetType.getInterfaces()[0].getInterfaces().length == 0, "Only single-level inheritance supported: %s", new Object[]{targetType.getSimpleName()});
}

为何会做这个限制目前未知,感觉很奇怪,如果有人知道的话麻烦告诉一声。

解决办法

    spring boot 默认会使用 SpringMvcContract 去实现
    代码位置:org.springframework.cloud.openfeign.FeignClientsConfiguration

    @Bean
    @ConditionalOnMissingBean
    public Contract feignContract(ConversionService feignConversionService) {
        return new SpringMvcContract(this.parameterProcessors, feignConversionService);
    }

    通过代码我们可以知道,如果我们自己提供一个实现,就可以替换掉
    拷贝源码实现自己的Contract,然后把上面的验证注释掉;
    编写一个 Configuration,注册自己实现的 Contract;

   代码大概这样:

@Configuration
	public class FeignConfig {
    @Autowired(
            required = false
    )
    private List<AnnotatedParameterProcessor> parameterProcessors = new ArrayList();

    @Autowired(
            required = false
    )
    private List<FeignFormatterRegistrar> feignFormatterRegistrars = new ArrayList();

    @Bean
    public Contract feignContract( ConversionService feignConversionService) {
        return new MContract(this.parameterProcessors, feignConversionService);
    }

    @Bean
    public FormattingConversionService feignConversionService() {
        FormattingConversionService conversionService = new DefaultFormattingConversionService();
        Iterator var2 = this.feignFormatterRegistrars.iterator();

        while(var2.hasNext()) {
            FeignFormatterRegistrar feignFormatterRegistrar = (FeignFormatterRegistrar)var2.next();
            feignFormatterRegistrar.registerFormatters(conversionService);
        }

        return conversionService;
    }
}

解决方法-补充

按照上面的思路,只能保证你的代码能运行,但无法调用到具体的服务
因为会出现路径不正确的问题,本来应该是 /api/get 会变成 /get 
源码位置,逻辑大概是:如果你有继承,使用继承类上的@RequestMapping

		protected MethodMetadata parseAndValidateMetadata(Class<?> targetType, Method method) {
	        if (targetType.getInterfaces().length == 1) {
                this.processAnnotationOnClass(data, targetType.getInterfaces()[0]);
            }

            this.processAnnotationOnClass(data, targetType);

而 processAnnotationOnClass 方法的实现,逻辑大概是 : 如果该类有继承就不处理。

 protected void processAnnotationOnClass(MethodMetadata data, Class<?> clz) {
        if (clz.getInterfaces().length == 0) {
            RequestMapping classAnnotation = (RequestMapping)AnnotatedElementUtils.findMergedAnnotation(clz, RequestMapping.class);
            if (classAnnotation != null && classAnnotation.value().length > 0) {
                String pathValue = Util.emptyToNull(classAnnotation.value()[0]);
                pathValue = this.resolve(pathValue);
                if (!pathValue.startsWith("/")) {
                    pathValue = "/" + pathValue;
                }

                data.template().insert(0, pathValue);
            }
        }

    }

 与上面的逻辑进行对应,结果就是 如果接口有继承,只会使用父类的@RequestMapping

 所以,最后只需要在自己实现的 MContract 中将该逻辑改变就好

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值