当前位置: 首页 > ds >正文

Feign异步模式丢失上下文问题

Feign异步模式丢失上下文问题

问题描述

当我们使用异步对我们代码进行操作优化时,代码中使用了RequestContextHolder去获取上下文的数据,当我们执行原来可以执行的业务时发现报了空指针异常或数据为空,这是为什么呢?

image-20250516193327144

原理解释

通过源码我们可以看出来,RequestContextHolder本质的是使用了ThreadLocal作为上下文的实现方式,但ThreadLocal只在自己线程中才可以读取到数据,但我们开启了异步线程,导致数据在不同的线程中为空,那我们怎么解决呢?

image-20250516193412987

解决方法

1、在主线程中读取出主线程的数据,通过RequestContextHolder将数据注入到子线程中即可解决此问题

@Overridepublic OrderConfirmVo confirmOrder() throws ExecutionException, InterruptedException {OrderConfirmVo confirmVo = new OrderConfirmVo();MemberLoginTo memberLoginTo = loginToThreadLocal.get();System.out.println("主线程的id:"+Thread.currentThread().getId());// 主线程的threadLocal数据,注意threadLocal中的数据只是在本线程中生效,若启用异步线程则会出现线程读取不到数据的问题RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();// 1、远程查询所有的收货地址的列表CompletableFuture<Void> addressFuture = CompletableFuture.runAsync(() -> {// 将主线程的threadLocal共享到子线程,避免出现读取不到子线程上下文数据的问题System.out.println("当前线程的id:"+Thread.currentThread().getId());RequestContextHolder.setRequestAttributes(requestAttributes);List<MemberAddressVo> address = memberFeignService.getAddress(memberLoginTo.getId());confirmVo.setAddress(address);}, executor);CompletableFuture<Void> CartItemFuture = CompletableFuture.runAsync(() -> {// 2、远程查询购物车的购物项列表// 将主线程的threadLocal共享到子线程,避免出现读取不到子线程上下文数据的问题System.out.println("当前线程的id:"+Thread.currentThread().getId());RequestContextHolder.setRequestAttributes(requestAttributes);List<OrderItemVo> userCartItems = cartFeignService.getUserCartItems();confirmVo.setOrderItems(userCartItems);// feign 在远程调用之前要构造请求,会调用很多的拦截器}, executor);return confirmVo;}

2、在主线程中使用RequestContextHolder.setRequestAttributes(requestAttributes,true);将主线程的数据共享即可解决此问题

@Overridepublic OrderConfirmVo confirmOrder() throws ExecutionException, InterruptedException {OrderConfirmVo confirmVo = new OrderConfirmVo();MemberLoginTo memberLoginTo = loginToThreadLocal.get();System.out.println("主线程的id:"+Thread.currentThread().getId());// 主线程的threadLocal数据,注意threadLocal中的数据只是在本线程中生效,若启用异步线程则会出现线程读取不到数据的问题RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();// 开启线程数据共享RequestContextHolder.setRequestAttributes(requestAttributes,true);// 1、远程查询所有的收货地址的列表CompletableFuture<Void> addressFuture = CompletableFuture.runAsync(() -> {// 将主线程的threadLocal共享到子线程,避免出现读取不到子线程上下文数据的问题System.out.println("当前线程的id:"+Thread.currentThread().getId());
//            RequestContextHolder.setRequestAttributes(requestAttributes);List<MemberAddressVo> address = memberFeignService.getAddress(memberLoginTo.getId());confirmVo.setAddress(address);}, executor);CompletableFuture<Void> CartItemFuture = CompletableFuture.runAsync(() -> {// 2、远程查询购物车的购物项列表// 将主线程的threadLocal共享到子线程,避免出现读取不到子线程上下文数据的问题System.out.println("当前线程的id:"+Thread.currentThread().getId());
//            RequestContextHolder.setRequestAttributes(requestAttributes);List<OrderItemVo> userCartItems = cartFeignService.getUserCartItems();confirmVo.setOrderItems(userCartItems);// feign 在远程调用之前要构造请求,会调用很多的拦截器}, executor);return confirmVo;}

要构造请求,会调用很多的拦截器
}, executor);
return confirmVo;
}


http://www.xdnf.cn/news/6771.html

相关文章:

  • 云轴科技ZStack官网上线Support AI,智能助手助力高效技术支持
  • 如何用PDO实现安全的数据库操作:避免SQL注入
  • GTS-400 系列运动控制器板卡介绍(三十三)---运动程序单线程累加求和
  • 【漫话机器学习系列】262.交叉项(Interaction Term)
  • redisson基础
  • 云基内容中台构建企业智慧实践
  • Linux系统启动相关:vmlinux、vmlinuz、zImage,和initrd 、 initramfs,以及SystemV 和 SystemD
  • 数据如何驱动互联网一体化发展?
  • 大模型——Crawl4AI使用JsonCssExtractionStrategy进行结构化数据提取
  • 【专利信息服务平台-注册/登录安全分析报告】
  • 如何通过URL链接让亚马逊网站返回指定像素大小的产品主图片
  • 今日积累:若依框架配置QQ邮箱,来发邮件,注册账号使用
  • 香橙派Zero3跨网络音乐服务系统搭建与内网穿透技术应用实践
  • android studio clone子分支
  • logrotate按文件大小进行日志切割
  • 面试题:详细分析Arraylist 与 LinkedList 的异同
  • Qt—用SQLite实现简单的注册登录界面
  • 基于大数据的租房信息可视化系统的设计与实现【源码+文档+部署】
  • springCloud/Alibaba常用中间件之Seata分布式事务
  • elementUI源码学习
  • 【RabbitMQ】消息丢失问题排查与解决
  • 红黑树实现
  • C语言单链表应用详解
  • flutter缓存网络视频到本地,可离线观看
  • java 使用zxing生成条形码(可自定义文字位置、边框样式)
  • Chrome代理IP配置教程常见方式附问题解答
  • 华为网路设备学习-22(路由器OSPF-LSA及特殊详解)
  • 对称二叉树的判定:双端队列的精妙应用
  • python自学笔记2 数据类型
  • 性能测试详解