前言

SpringCloud微服务之间调用一般使用OpenFeign,认证鉴权一般是通过添加特定的请求头。那么OpenFeign请求其他微服务的时候也要携带特定的请求头,这时候就需要一个拦截器,统一添加请求头。

一、请求拦截

最简单的方案就是实现feign.RequestInterceptor接口。这样使用OpenFeign请求其他微服务接口的时候就会携带请求头,保证认证通过。

@Slf4j
@Configuration
public class CustomFeignRequestInterceptor implements RequestInterceptor {


    @Override
    public void apply(RequestTemplate template) {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();

        if (attributes != null) {
            HttpServletRequest request = attributes.getRequest();
            // 转发token
            template.header("token", request.getHeader("token"));
        }
    }
}

二、多线程调用导致问题

有时候需要多线程调用FeignClient来获取数据,但是会导致无法携带token的异常。经过断点发现,使用多线程调用FeignClient时,在拦截器中无法获取ServletRequestAttributes。因此怀疑是多线程导致Request数据丢失,具体原因未深究。解决办法就是从主线程拿到ServletRequestAttributes,然后在异步线程里再放进Request中。

示例代码如下

//从主线程获取所有request数据
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();

executor.execute(() -> {
    //其他线程放入request数据
    RequestContextHolder.setRequestAttributes(requestAttributes);
           
});

写在最后的话

多线程调用FeignClient其实很少用到,但是有些场景下为了减少耗时不得不用。当初遇到这个问题,花了好长时间才解决,毕竟万事开头难。希望这篇文档能给你带来一点启发。

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐