给特别规则FeignClient增加统一的RequestInterceptor

需求背景:

在微服务横行天下的今天,Spring Cloud OpenFeign 早就成了我们服务间调度的主要远程调用手段。

在Feign进行远程调度的时候,难免会做一些心跳,权限的校验,来保证调度过程的相对安全。

但对于外部系统来说,有时候这些“额外信息”反而成了负担(笔者就遇到了调用外部系统时由于外部系统设置了对 http head 大小的设置,导致调用400错误)。

常见的对http head 大小限制如:

1.服务对请求头大小的限制

 2.网关对请求头大小的限制

当遇到这种情况时,我们就需要对不同的Feign调用添加不同的RequestInterceptor;

参考Spring Cloud OpenFeign 的文档手册

 

 可以根据不同的feignName去配置对应的拦截器;

但是项目系统有很多FeignClient调用时,就显得配置比较繁琐。

那我们怎么对项目系统内部的FeignClient进行统一拦截器拦截,外部调用做其他处理呢;

需要我们去分析一下FeignClient的工厂类FeignClientFactoryBean;

在用户没有其他自定义的配置文件时,都会调用根据contextId去获取配置文件;

那么我们可以通过利用这个特性,通过BeanFactoryPostProcessor去给

feignClientProperties添加对应contextId的过滤器;
@Slf4j
@Component
public class FeignConfigBeanFactoryPostProcessor implements BeanFactoryPostProcessor {

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
//获取FeignClientProperties
        FeignClientProperties feignClientProperties = configurableListableBeanFactory.getBean(FeignClientProperties.class);
//获取FeignClientBeanFacoty数组
        String [] feignClientBeanFactoryArray = configurableListableBeanFactory.getBeanNamesForAnnotation(FeignClient.class);
//自定义FeignClientConfiguration
        FeignClientProperties.FeignClientConfiguration feignClientConfiguration = new FeignClientProperties.FeignClientConfiguration();
//添加自定义CustomerFeignInterceptor
        feignClientConfiguration.setRequestInterceptors(Arrays.asList(new Class[]{CustomerFeignInterceptor.class}));
        for(String feignClientBeanFactory : feignClientBeanFactoryArray){
            BeanDefinition beanDefinition = configurableListableBeanFactory.getBeanDefinition(feignClientBeanFactory);
//公司内部系统的内部统一命名为"abc-***",如果不统一,也可以通过配置文件或者其他方式去记录需要统一处理的FeignClient;
            if(Objects.nonNull(beanDefinition.getPropertyValues().get("name")) && beanDefinition.getPropertyValues().get("name").toString().startsWith("abc-")){
//根据contextId添加FeignClientConfiguration           
feignClientProperties.getConfig().put(Objects.requireNonNull(beanDefinition.getPropertyValues().get("contextId")).toString(),feignClientConfiguration);
            }
        }
    }
}

这样,就做到了给一些特定的FeignClient去添加统一的RequestInterceptor;

注:Feign.Builder在添加requestInterceptor的时候存储的是个List数组

@FeignClient(value = "abc-web",contextId = "abc-web",configuration = {CustomerFeignInterceptor.class})

当我们添加FeignConfigBeanFactoryPostProcessor 的同时在@FeignClient的configuration 写入同一个CustomerFeignInterceptor时,CustomerFeignInterceptor会调用多次

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值