Feign远程调用丢失请求头

news2024/11/26 0:31:26

前言

我们在写服务端项目的时候,总会限制对某些资源的访问,最常见的就是要求用户先登录才能访问资源,当用户登录后就会将此次会话信息保存进session,同时返回给浏览器指定的cookie键值,下次浏览器再次访问,请求头中就会携带这个cookie,我们也以次来识别用户的登录状态,做出正确响应。

一、问题

有时候,我们先行登录,然后访问服务A的某个方法,请求头中携带cookie,标识我们已经登录。但若是我们访问的目标方法在执行过程中使用feign进行远程调用服务B,而服务B也要先判断登录状态,我们可能发现服务B会调用失败,或者说拿不到数据,理由是服务B认为我们并未登录。而这时,如果我们直接从浏览器访问服务B的这个方法却能得到一个成功的响应。
在这里插入图片描述

二、查看源码

1、使用feign进行远程调用时,首先判断目标方法类型,如果是 toString(),hashCode(),equals()这几个方法,那就是本地直接完成了

在这里插入图片描述

2、执行真正的远程调用的方法

在这里插入图片描述

3、根据模板template来创建请求request(默认的情况feign是不会帮我们把原请求头参数复制到新请求的请求头上的),然后进行客户端client调用

在这里插入图片描述
4、但是创建请求时,会先调用所有的拦截器RequestInterceptors

在这里插入图片描述

5、所以我们可以自己向容器中注册一个拦截器RequestInterceptor,在这个拦截器中重写apply方法,在apply方法中把老请求的cookie复制到新request的请求头中,完成请求头的同步。(然后targetRequest 方法就会调用拦截器的apply方法,进行返回)

总结:

  • feign远程调用,自己创建一个新的request对象,按照指定的路径和参数发起新的请求,并得到响应结果。但是这个新的request对象请求头为空,所以丢失了原先请求中的数据。

  • feign在创建新的request对象时,会调用一系列容器中的RequestInterceptor对象,执行其apply方法,对这个创建好的request进行增强,再去真正执行请求。但是默认情况下容器中不存在这类拦截器对象。

  • 我们可以自己向容器中注册一个RequestInterceptor,在其apply方法体内,获取到原始request,将其数据取出,赋值到新的request中,完成请求头的同步。RequestContextHolder借助ThreadLocal将每一个原始请求与tomcat为其分配的线程绑定,之后,只要在同个线程内,随时随地都可轻易获取到原始request。而我们是在apply方法体内,通过 RequestContextHolder.getRequestAttributes() 获取的。RequestContextHolder是借助ThreadLocal将每一个原始请求与tomcat为其分配的线程绑定,之后,只要在同个线程内,随时随地都可轻易获取到原始request。

三、解决

在这里插入图片描述

1、同步时

直接向spring容器注入RequestInterceptor拦截器即可

/**
* Feign
* @return
*/
@Bean
public RequestInterceptor requestInterceptor(){
   return requestTemplate -> {
       //1、从RequestContextHolder获取原始请求的请求数据(请求参数、请求头等)
       ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();
       HttpServletRequest request = attributes.getRequest();
       //2、同步请求头数据
       Enumeration<String> headerNames = request.getHeaderNames();
       if (headerNames != null) {
           while (headerNames.hasMoreElements()) {
               String name = headerNames.nextElement();
               String values = request.getHeader(name);
               requestTemplate.header(name, values);
           }
       }
   };
}

2、异步时

如果请求中使用了异步,也就是多线程,就算配置了上面的配置也会导致feign请求头丢失,因为请求头信息是通过threadLocal保存的,也就是只有在同一个线程中才能使用请求中的请求头并且同步初始请求头信息到feign请求中

解决办法

在异步调用时主动将请求头覆盖到异步线程的请求上下文中

// 通过请求上下文获取请求信息
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
CompletableFuture<Void> addressFuture = CompletableFuture.runAsync(() -> {
    // 远程查询所有的收货地址列表
    // 在该线程中添加请求信息
    RequestContextHolder.setRequestAttributes(requestAttributes);
    List<MemberAddressVo> address = memberFeignService.getAddress(memberRespVo.getId());
    orderConfirmVo.setAdress(address);
}, executor);CompletableFuture<Void> cartFuture = CompletableFuture.runAsync(() -> {
    // 远程查询购物车所有选中的购物想
    // 在该线程中添加请求信息
    RequestContextHolder.setRequestAttributes(requestAttributes);
    List<OrderItemVo> currentUserItems = cartFeignService.getCurrentUserItems();
    orderConfirmVo.setItems(currentUserItems);
}, executor);

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1020267.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【虚拟现实】2023年VR技术的10个应用行业

1.医疗保健 现代医疗保健的培训方式离不开VR虚拟现实。。由于医疗行业的特殊性&#xff0c;不允许拿大量的病人来练手&#xff0c;但医疗又非常注重实践&#xff0c;一些新手医生就缺乏锻炼的机会&#xff0c;而VR虚拟现实技术很好的解决了这一问题。医生可以在高清晰、低延时…

【C++】搜索二叉树底层实现

目录 一&#xff0c;概念 二&#xff0c;实现分析 1. 插入 &#xff08;1.&#xff09;非递归版本 &#xff08;2.&#xff09;递归版本 2. 打印搜索二叉树 3.查找函数 &#xff08;1.&#xff09;非递归版本 &#xff08;2.&#xff09;递归版本 4. 删除函数&#x…

【Linux-Day13-生产者消费者模型】

生产者消费者模型 生产者消费者问题概述 生产者/消费者问题&#xff0c;也被称作有限缓冲问题。可以描述为&#xff1a;两个或者更多的线程共享同一个缓冲 区&#xff0c;其中一个或多个线程作为“生产者”会不断地向缓冲区中添加数据&#xff0c;另一个或者多个线程作为“消…

基于CNN-LSTM的时序预测MATLAB实战

一、算法原理 1.1 CNN原理 卷积神经网络具有局部连接、权值共享和空间相关等特性。卷积神经网络结构包含卷积层、激活层和池化层。 &#xff08;a&#xff09;二维卷积层将滑动卷积滤波器应用于输入。该层通过沿输入垂直和水平方向 移动滤波器对输入进行卷积&#xff0c;并计…

阿里云无影电脑:免费体验无影云电脑3个月

阿里云无影云电脑免费领取流程&#xff0c;免费无影云电脑配置为4核8G&#xff0c;可以免费使用3个月&#xff0c;阿里云百科分享阿里云无影云电脑&#xff08;云桌面&#xff09;免费申请入口、申请流程及免费使用限制条件说明&#xff1a; 目录 阿里云无影云电脑免费申请入…

汉威科技亮相上海传感器展并发表主题演讲,智能传感器大有可为

9月15日&#xff0c;第8届中国&#xff08;上海&#xff09;国际传感器技术与应用展览会圆满落幕&#xff0c;该展会吸引了逾400家传感领域国内外的企业、100余家专业传感应用单位、500余位传感大咖共同参与&#xff0c;展会观众达30000人。作为全球三大传感器展之一的盛会&…

2023年最热门的编程语言:前进的趋势和机会

2023年最热门的编程语言&#xff1a;前进的趋势和机会 2023年最热门的编程语言&#xff1a;前进的趋势和机会摘要引言1. 编程语言的热门趋势1.1 新兴编程语言的崛起1.2 编程语言的可持续性发展1.3 跨平台编程语言的兴起1.4 人工智能和机器学习编程语言的需求 2. 编程语言职业机…

Informatica使用操作流程--存储过程调用、序列生成器 使用案例5

映射 [创建]连接工作流 --创建工作流W_EMP_DEPT_COUNT,连接任务S_EMP_DEPT_COUNT,ctrls保存 --右击工作流-->通过任务启动工作流 存储数据的地方查验数据

00后卷王的软件测试面试秘籍(含文档)

前言 前段时间去面试了一个公司&#xff0c;成功拿到了offer&#xff0c;薪资也从12k涨到了20k&#xff0c;对于工作都还没两年的我来说&#xff0c;还是比较满意的&#xff0c;毕竟一些工作3、4年的可能还没我高。 我可能就是大家说的卷王&#xff0c;感觉自己年轻&#xff…

MybatisMybatisPlus 操作 jsonb 格式数据

最近有用到postgresql&#xff0c;里面的一个特色数据类型便是jsonb&#xff0c;和json差不多&#xff0c;但是查询比较快&#xff0c;关于概念&#xff0c;这里就提一句&#xff0c;不赘述。 我们先来看下用mybatisplus&#xff0c;首先是查询数据。 依赖&#xff1a; <d…

基于springboot车辆充电桩管理系统springboot000

大家好✌&#xff01;我是CZ淡陌。一名专注以理论为基础实战为主的技术博主&#xff0c;将再这里为大家分享优质的实战项目&#xff0c;本人在Java毕业设计领域有多年的经验&#xff0c;陆续会更新更多优质的Java实战项目&#xff0c;希望你能有所收获&#xff0c;少走一些弯路…

【百问百答】可靠性基础知识第八期

1、什么是加速度频谱密度值(ASD) ? 表示随机信号的各个频率分量所包的加速度方均值在频域上是如何分布的。通常用ASD表示。 2、什么是功率频谱密度值(PSD) ? 表示随机信号的各个频率分量所包的功率在频域上是怎样分布的。通常用PSD表示&#xff0c;单位&#xff1a;g2/Hz。 0…

如何快速从 ETL 到 ELT?火山引擎 ByteHouse 做了这三件事

更多技术交流、求职机会&#xff0c;欢迎关注字节跳动数据平台微信公众号&#xff0c;回复【1】进入官方交流群 前言 当涉及到企业分析场景时&#xff0c;所使用的数据通常源自多样的业务数据&#xff0c;这些数据系统大多采用以行为主的存储结构&#xff0c;比如支付交易记录…

02Spring框架的特点以及jar包下载

Spring框架 Spring简介 Spring是由Rod Johnson创建的一个实现了IoC思想的开源框架, Spring最初的出现是为了解决EJB臃肿的设计以及难以测试等问题 Spring是为了解决企业应用开发的复杂性而创建的,从简单性、可测试性和松耦合的角度而言任何Java应用都可以从Spring中受益 Sp…

2023-驾驶舱数据指标体系建设

一、什么是领导驾驶舱&#xff1f; 领导驾驶舱&#xff0c;它以驾驶舱的形式&#xff0c;通过各种图表形象的展示企业运行的关键指标&#xff08;KPI&#xff09;&#xff0c;直观的监测企业运营情况&#xff0c;并可以对异常关键指标预警和挖掘分析。以根据管理和业务的需要&a…

期权合约到期日强平了还要扣手续费嘛?

国内目前的50ETF期权交易是会收取平仓的手续费的&#xff0c;期权手续费是双向收费&#xff0c;开仓收取一次、平仓收取一次。国内不同券商和期权分仓平台的手续费标准不同&#xff0c;下文介绍期权合约到期日强平了还要扣手续费嘛&#xff1f;本文来自&#xff1a;期权酱 一、…

EFLAGS寄存器与JCC指令

EFLAGS寄存器 EFLAGS寄存器有32位&#xff0c;EFLAGS 寄存器的标志位可以通过各种指令进行操作和判断&#xff0c;例如条件分支指令、算术指令和控制指令等。程序可以根据标志位的值来进行条件判断和控制流程&#xff0c;从而实现不同的逻辑和功能。 EFLAGS 寄存器的各个位和…

js写一个判断字符串是否能够转为JSON 的函数

其实非常简单 这里我们需要涉及到 捕获异常 因为如果你直接在if里面转 我已经试过了 直接就报错了 一点面子不给 我们写一个这样的函数 function isJsonString(str) {try {JSON.parse(str);return true;} catch (e) {return false;} }编写如下代码 console.log(isJsonString(…

Flutter的路由router-页面跳转

文章目录 概念介绍基本路由&#xff08;Basic Routing&#xff09;跳转到某个页面弹出页面 命名路由&#xff08;Named Routing&#xff09;第三方路由管理库&#xff08;Third-Party Routing Libraries&#xff09; Android原生的路由Intent-based Routing&#xff08;基于Int…

分析数组,结构体在反汇编中存储

本文会在IDA中分析数组&#xff0c;结构体在内存中的存储 目录 IDA分析数组存储 IDA分析结构体存储 传递参数的方式 IDA分析数组存储 测试代码如下&#xff1a; /************************************************************************/ /*Author : 玄都大…