【解决】Feign远程调用丢失请求头问题

问题

在写项目的过程中,使用OpenFeign进行远程调用服务时,获取不到原请求头中携带的cookie信息,也就是Feign远程调用丢失请求头问题

http://order.gulimall.com/toTrade:

public OrderConfirmVo getConfirmOrder() {
	OrderConfirmVo vo = new OrderConfirmVo();
	// 远程调用 获取被选中的购物车中的购物项项信息
	List<OrderItemVo> orderItemVo = cartFeignService.getCheckedItem();
	vo.setItems(orderItemVo);
	
	return vo;
}

远程调用接口:

@FeignClient("gulimall-cart")
public interface CartFeignService {

    @PostMapping("/checkedItem")
    List<OrderItemVo> getCheckedItem();
}

被调用方法:

@PostMapping("/checkedItem")
public List<CartItemVo> getCheckedItem() {
    String cookie = request.getHeader("Cookie");
    log.info("接收到携带Cookie: {}", cookie);
    return cartService.getCheckedItem();
}

问题:

  • 发送请求,http://order.gulimall.com/toTrade,并且携带请求头Cookie=GULISESSION=ZWE2OWI1YzMtYzQxNy00YTAwLWI1M2YtNGNhMzI1MDg2OTgw,执行目标方法getConfirmOrder()
  • getConfirmOrder()方法内部远程调用getCheckedItem()
  • getCheckedItem(),打印日志:接收到携带Cookie: null

导致原因

在这里插入图片描述
在使用OpenFeign进行远程调用时,底层会给我们生成一个新的request请求去请求被调用的服务,并且这个请求不携带任何请求头,从而导致了在被调用方法中获取不到请求头cookie的问题。
在这里插入图片描述

如何解决

查看上述targetRequest方法:
在这里插入图片描述
在远程调用方法之前,会执行很多的拦截器,我们可以利用这些拦截器来给OpenFeign生成的新的request请求包装一些其它参数,因此,我们只需要在容器配置一个RequestInterceptor类型的拦截器,将原请求中携带的请求头Cookie封装到新的请求中即可。
创建配置类:

@Configuration
public class FeignConfig {

    @Bean
    public RequestInterceptor requestInterceptor() {
        return new RequestInterceptor() {
            @Override
            public void apply(RequestTemplate template) {
                // 获取原请求
                ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
                // 原请求 也就是http://order.gulimall.com/toTrade 
                HttpServletRequest request = attributes.getRequest();
                // 获取原请求中携带的Cookie请求头
                String cookie = request.getHeader("Cookie");
                // 将cookie 同步到新的请求的请求头中
                template.header("Cookie", cookie);
            }
        };
    }

}

注意:这里RequestContextHolder.getRequestAttributes()方法获取原请求信息,RequestContextHolder是基于本地线程线程作用域(TreadLocal)获取的,如果请求映射到的controller控制器方法和执行到这里使用的线程不同,这里是获取不到原请求的。
再次发送请求,打个断点,测试原请求中的Cookie是否能够同步到新生成请求的请求头中:
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值