RequestContextHolder多线程获取不到request对象
RequestContextHolder多线程获取不到request对象,调用feign接口时,在Feign中的RequestInterceptor也获取不到HttpServletRequest问题解决方案。
1.RequestContextHolder多线程获取不到request对象
异常信息,报错如下:
2024-07-09 22:06:32.320 [pool-5-thread-2] ERROR com.mergeplus.handler.ObjectHandler:227 - class: interface org.jeecg.common.system.api.client.SysFeignClient, methodName=mergeRegion, error: {}
java.lang.IllegalStateException: No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request.at org.springframework.web.context.request.RequestContextHolder.currentRequestAttributes(RequestContextHolder.java:131)at org.springframework.web.context.support.WebApplicationContextUtils.currentRequestAttributes(WebApplicationContextUtils.java:313)at org.springframework.web.context.support.WebApplicationContextUtils$RequestObjectFactory.getObject(WebApplicationContextUtils.java:329)at org.springframework.web.context.support.WebApplicationContextUtils$RequestObjectFactory.getObject(WebApplicationContextUtils.java:324)at org.springframework.beans.factory.support.AutowireUtils$ObjectFactoryDelegatingInvocationHandler.invoke(AutowireUtils.java:283)at jdk.proxy2/jdk.proxy2.$Proxy179.getHeaderNames(Unknown Source)at com.mergeplus.handler.ObjectHandler.lambda$doHandler$0(ObjectHandler.java:155)at java.base/java.util.concurrent.CompletableFuture$AsyncSupply.run$$$capture(CompletableFuture.java:1768)at java.base/java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java)at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)at java.base/java.lang.Thread.run(Thread.java:833)
异常错误截图:

2.解决方案
// 设置子线程共享(重点)final RequestAttributes attributes = RequestContextHolder.getRequestAttributes();merges.stream().map(e -> CompletableFuture.supplyAsync(() -> {JSONObject returnMap = null;try {if (e.getClientBean() != null) {// 设置当前线程的 RequestAttributes(重点)RequestContextHolder.setRequestAttributes(attributes);Object returnValue = e.getMethod().invoke(e.getClientBean(), jsonObject.get(e.getSourceKey()));if (returnValue == null) {return e;}returnMap = JSON.parseObject(JSON.toJSONString(returnValue));if (returnMap == null || returnMap.isEmpty()) {return e;}result.put(e.getTargetKey(), returnMap.get(jsonObject.get(e.getSourceKey())));} else {if (e.getUrl() == null || e.getUrl().trim().length() == 0) {return e;}//设置Http的HeaderHttpHeaders headers = new HttpHeaders();headers.setContentType(MediaType.APPLICATION_JSON);//设置访问参数HashMap<String, Object> params = new HashMap<>();if (e.getKey() == null || e.getKey().trim().length() == 0) {params.put(e.getSourceKey(), jsonObject.get(e.getSourceKey()));}//设置访问的EntityHttpEntity entity = new HttpEntity<>(params, headers);// todoResponseEntity<Object> exchange = restTemplate.exchange(e.getUrl(), HttpMethod.GET, entity, Object.class);if (exchange == null) {return e;}Object body = exchange.getBody();if (body == null) {return e;}returnMap = JSON.parseObject(JSON.toJSONString(body));if (returnMap == null || returnMap.isEmpty()) {return e;}result.put(e.getTargetKey(), returnMap.get(jsonObject.get(e.getSourceKey())));// if (body instanceof Map) {
// returnMap = (Map) body;
// if (returnMap == null || returnMap.isEmpty()) {
// return e;
// }
// result.put(e.getTargetKey(), returnMap.get(jsonObject.get(e.getSourceKey())));
// }}} catch (Exception ex) {log.error("class: {}, methodName={}, error: {}", e.getClientBeanClazz(), e.getMethod().getName(), ex);} finally {RequestContextHolder.resetRequestAttributes(); // 记得在最后重置请求属性(重点)}return e;}, executor)).toList().stream().map(CompletableFuture::join).collect(Collectors.toList());


FeignInterceptorConfig代码
package org.jeecg.config;import java.io.IOException;
import java.util.*;import feign.RequestTemplate;
import jakarta.servlet.http.HttpServletRequest;
import org.apache.commons.lang3.StringUtils;
import org.jeecg.common.config.mqtoken.UserTokenContext;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.util.DateUtils;
import org.jeecg.common.util.PathMatcherUtil;
import org.jeecg.common.util.SpringContextUtils;
import org.jeecg.common.util.TokenUtils;
import org.jeecg.config.sign.interceptor.SignAuthConfiguration;
import org.jeecg.config.sign.util.HttpUtils;
import org.jeecg.config.sign.util.SignUtil;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
import org.springframework.cloud.openfeign.FeignAutoConfiguration;
import org.springframework.cloud.openfeign.support.SpringDecoder;
import org.springframework.cloud.openfeign.support.SpringEncoder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.context.annotation.Scope;
import org.springframework.http.MediaType;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson.support.config.FastJsonConfig;
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;import feign.Feign;
import feign.Logger;
import feign.RequestInterceptor;
import feign.codec.Decoder;
import feign.codec.Encoder;
import feign.form.spring.SpringFormEncoder;
import lombok.extern.slf4j.Slf4j;/*** @Description: FeignConfig* @author: JeecgBoot*/
@ConditionalOnClass(Feign.class)
@AutoConfigureBefore(FeignAutoConfiguration.class)
@Slf4j
@Configuration
public class FeignInterceptorConfig {@Beanpublic RequestInterceptor requestInterceptor() {return requestTemplate -> {ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();if (requestAttributes == null) {return;}//1.获取请求对象HttpServletRequest request = requestAttributes.getRequest();Enumeration<String> headerNames = request.getHeaderNames();if (headerNames == null || !headerNames.hasMoreElements()) {return;}//2.获取请求对象中的所有的头信息(网关传递过来的)while (headerNames.hasMoreElements()) {String name = headerNames.nextElement();//头的名称// 跳过content-length,不然可能会报too many bites written问题if ("content-length".equalsIgnoreCase(name)) {continue;}String value = request.getHeader(name);//头名称对应的值// System.out.println("name:" + name + "::::::::value:" + value);//3.将头信息传递给feign (restTemplate)requestTemplate.header(name,value);// if (CommonConstant.X_ACCESS_TOKEN.equals(name) && StringUtils.isBlank(value)) {
// String token = UserTokenContext.getToken();
// requestTemplate.header(CommonConstant.X_ACCESS_TOKEN, token);
// }}//================================================================================================================//针对特殊接口,进行加签验证 ——根据URL地址过滤请求 【字典表参数签名验证】// todoif (PathMatcherUtil.matches(Arrays.asList(PathMatcherUtil.SIGN_URL_LIST),requestTemplate.path())) {
// if (PathMatcherUtil.matches(Arrays.asList(SignAuthConfiguration.SIGN_URL_LIST),requestTemplate.path())) {try {log.info("============================ [begin] fegin api url ============================");log.info(requestTemplate.path());log.info(requestTemplate.method());String queryLine = requestTemplate.queryLine();String questionMark="?";if(queryLine!=null && queryLine.startsWith(questionMark)){queryLine = queryLine.substring(1);}log.info(queryLine);if(requestTemplate.body()!=null){log.info(new String(requestTemplate.body()));}SortedMap<String, String> allParams = HttpUtils.getAllParams(requestTemplate.path(),queryLine,requestTemplate.body(),requestTemplate.method());String sign = SignUtil.getParamsSign(allParams);log.info(" Feign request params sign: {}",sign);log.info("============================ [end] fegin api url ============================");requestTemplate.header(CommonConstant.X_SIGN, sign);requestTemplate.header(CommonConstant.X_TIMESTAMP, String.valueOf(System.currentTimeMillis()));} catch (IOException e) {e.printStackTrace();}}//================================================================================================================};}}
3.相关大数据学习demo地址:
https://github.com/carteryh/big-data
相关文章:
RequestContextHolder多线程获取不到request对象
RequestContextHolder多线程获取不到request对象,调用feign接口时,在Feign中的RequestInterceptor也获取不到HttpServletRequest问题解决方案。 1.RequestContextHolder多线程获取不到request对象 异常信息,报错如下: 2024-07-0…...
打造高效工作与生活质量的完美平衡
在快节奏的编程行业中,保持健康的工作与生活平衡是至关重要的。长时间坐在电脑前、面对紧凑的项目截止日期和频繁的加班文化,很容易导致身心健康问题,如眼睛疲劳、颈部和背部疼痛、压力累积、睡眠障碍乃至慢性疾病。因此,采取积极…...
【零基础】学JS之APIS第四天
💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 非常期待和您一起在这个小…...
走进linux
1、为什么要使用linux 稳定性和可靠性: Linux内核以其稳定性而闻名,能够持续运行数月甚至数年而不需要重新启动。这对于服务器来说至关重要,因为它们需要保持长时间的稳定运行,以提供持续的服务 安全性: Linux系统…...
智能家居开发新进展:乐鑫 ESP-ZeroCode 与亚马逊 ACK for Matter 实现集成
日前,乐鑫 ESP-ZeroCode 与亚马逊 Alexa Connect Kit (ACK) for Matter 实现了集成。这对智能家居设备制造商来说是一项重大进展。开发人员无需编写固件或开发移动应用程序,即可轻松设计符合 Matter 标准的产品。不仅如此,开发者还可以在短短…...
本地事务和分布式事务
一、本地事务 1、事务的基本特性 数据库事务的几个基本特性:原子性、一致性、隔离性、持久性。 原子性:一系列的操作整体不可拆分,要么同时成功,要么同时失败。 一致性:数据在事务的前后,业务整体一…...
昇思25天学习打卡营第14天|基于MindNLP的文本解码原理
基于MindNLP的文本解码原理 文本解码 文本解码是自然语言处理中的一个关键步骤,特别是在任务如机器翻译、文本摘要、自动回复生成等领域。解码过程涉及将编码器(如语言模型、翻译模型等)的输出转换为可读的文本序列。以下是一些常见的文本解码方法和原理: 1. 自回归解码:…...
Base64文件流查看下载PDF方法-CSDN
问题描述 数票通等接口返回的PDF类型发票是以Base64文件流的方式返回的,无法直接查看预览PDF发票, 处理方法 使用第三方在线工具:https://www.jyshare.com/front-end/61/ 在Html代码框中粘贴如下代码 <embed type"application/pd…...
基于TCP的在线词典系统(分阶段实现)(阻塞io和多路io复用(select)实现)
1.功能说明 一共四个功能: 注册 登录 查询单词 查询历史记录 单词和解释保存在文件中,单词和解释只占一行, 一行最多300个字节,单词和解释之间至少有一个空格。 2.功能演示 3、分阶段完成各个功能 3.1 完成服务器和客户端的连接 servic…...
设置DepthBufferBits和设置DepthStencilFormat的区别
1)设置DepthBufferBits和设置DepthStencilFormat的区别 2)Unity打包exe后,游戏内拉不起Steam的内购 3)Unity 2022以上Profiler.FlushMemoryCounters耗时要怎么关掉 4)用GoodSky资产包如何实现昼夜播发不同音乐功能 这是…...
MySQL零散拾遗
mysql中大小写敏感吗? MySQL数据库默认情况下是不区分大小写的,这意味着在查询时,字段名和值的大小写不会影响结果。然而,这种默认行为可能会根据操作系统和配置的不同而有所变化。 在某些操作系统上,比如Linux&…...
kali安装vulhub遇到的问题及解决方法(docker及docker镜像源更换)
kali安装vulhub: 提示:项目地址 https://github.com/vulhub/vulhub 项目安装: git clone https://github.com/vulhub/vulhub.git 安装docker 提示:普通用户请使用sudo: 首先安装 https 协议、CA 证书 apt-get in…...
开源数字人项目Hallo
硬件条件: gpu最低12G 软件: cuda需支持 Python选择3.10吧,我的版本3.11 源码: GitHub - fudan-generative-vision/hallo: Hallo: Hierarchical Audio-Driven Visual Synthesis for Portrait Image Animation models文件&…...
Linux 命令集
修改主机名/关机/重启 1)hostnamectl 命令 $ hostnamectl # 查看操作系统信息(内核、操作系统发行版本、主机名等) $ hostnamectl set-hostname redhatu8 # 修改主机名2)shutdown 关机 $ shutdown -h now # 马上关机3&#…...
QML 鼠标和键盘事件
学习目标:Qml 鼠标和键盘事件 学习内容 1、QML 鼠标事件处理QML 直接提供 MouseArea 来捕获鼠标事件,该操作必须配合Rectangle 获取指定区域内的鼠标事件, 2、QML 键盘事件处理,并且获取对OML直接通过键盘事件 Keys 监控键盘任意按键应的消…...
WPF引入多个控件库使用
目的 设计开发时有的控件库的一部分符合我们想要的UI样式,另一部分来自另一个控件库,想把两种库的样式做一个整合在同一个控件资源上。单纯通过引用的方式会导致原有样式被覆盖。这里通过设置全局样式的方式来实现。 1.安装控件库nuget包:H…...
【Linux】1w详解如何实现一个简单的shell
目录 实现思路 1. 交互 获取命令行 2. 子串分割 解析命令行 3. 指令的判断 内建命令 4. 普通命令的执行 补充:vim 文本替换 整体代码 重点思考 1.getenv和putenv是什么意思 2.代码extern char **environ; 3.内建命令是什么 4.lastcode WEXITSTATUS(sta…...
单目测距 单目相机测距 图片像素坐标转实际坐标的一种转换方案
需要相机位置固定 原图 红色的点是我们标注的像素点,这些红色的点我们知道它的像素坐标,以及以右下角相机位置为原点的x y 实际坐标数值 通过转换,可以得到整个图片内部其余像素点的实际坐标, 这些红色的点是通过转换关系生成的&…...
ensp防火墙综合实验作业+实验报告
实验目的要求及拓扑图: 我的拓扑: 更改防火墙和交换机: [USG6000V1-GigabitEthernet0/0/0]ip address 192.168.110.5 24 [USG6000V1-GigabitEthernet0/0/0]service-manage all permit [Huawei]vlan batch 10 20 [Huawei]int g0/0/2 [Huawei-…...
【大模型LLM面试合集】大语言模型基础_Word2Vec
Word2Vec 文章来源:Word2Vec详解 - 知乎 (zhihu.com) 1.Word2Vec概述 Word2Vec是google在2013年推出的一个NLP工具,它的特点是能够将单词转化为向量来表示,这样词与词之间就可以定量的去度量他们之间的关系,挖掘词之间的联系。 …...
vscode里如何用git
打开vs终端执行如下: 1 初始化 Git 仓库(如果尚未初始化) git init 2 添加文件到 Git 仓库 git add . 3 使用 git commit 命令来提交你的更改。确保在提交时加上一个有用的消息。 git commit -m "备注信息" 4 …...
Linux 文件类型,目录与路径,文件与目录管理
文件类型 后面的字符表示文件类型标志 普通文件:-(纯文本文件,二进制文件,数据格式文件) 如文本文件、图片、程序文件等。 目录文件:d(directory) 用来存放其他文件或子目录。 设备…...
TDengine 快速体验(Docker 镜像方式)
简介 TDengine 可以通过安装包、Docker 镜像 及云服务快速体验 TDengine 的功能,本节首先介绍如何通过 Docker 快速体验 TDengine,然后介绍如何在 Docker 环境下体验 TDengine 的写入和查询功能。如果你不熟悉 Docker,请使用 安装包的方式快…...
Vue3 + Element Plus + TypeScript中el-transfer穿梭框组件使用详解及示例
使用详解 Element Plus 的 el-transfer 组件是一个强大的穿梭框组件,常用于在两个集合之间进行数据转移,如权限分配、数据选择等场景。下面我将详细介绍其用法并提供一个完整示例。 核心特性与用法 基本属性 v-model:绑定右侧列表的值&…...
如何在看板中体现优先级变化
在看板中有效体现优先级变化的关键措施包括:采用颜色或标签标识优先级、设置任务排序规则、使用独立的优先级列或泳道、结合自动化规则同步优先级变化、建立定期的优先级审查流程。其中,设置任务排序规则尤其重要,因为它让看板视觉上直观地体…...
基于Flask实现的医疗保险欺诈识别监测模型
基于Flask实现的医疗保险欺诈识别监测模型 项目截图 项目简介 社会医疗保险是国家通过立法形式强制实施,由雇主和个人按一定比例缴纳保险费,建立社会医疗保险基金,支付雇员医疗费用的一种医疗保险制度, 它是促进社会文明和进步的…...
解决Ubuntu22.04 VMware失败的问题 ubuntu入门之二十八
现象1 打开VMware失败 Ubuntu升级之后打开VMware上报需要安装vmmon和vmnet,点击确认后如下提示 最终上报fail 解决方法 内核升级导致,需要在新内核下重新下载编译安装 查看版本 $ vmware -v VMware Workstation 17.5.1 build-23298084$ lsb_release…...
家政维修平台实战20:权限设计
目录 1 获取工人信息2 搭建工人入口3 权限判断总结 目前我们已经搭建好了基础的用户体系,主要是分成几个表,用户表我们是记录用户的基础信息,包括手机、昵称、头像。而工人和员工各有各的表。那么就有一个问题,不同的角色…...
【Java_EE】Spring MVC
目录 Spring Web MVC 编辑注解 RestController RequestMapping RequestParam RequestParam RequestBody PathVariable RequestPart 参数传递 注意事项 编辑参数重命名 RequestParam 编辑编辑传递集合 RequestParam 传递JSON数据 编辑RequestBody …...
【开发技术】.Net使用FFmpeg视频特定帧上绘制内容
目录 一、目的 二、解决方案 2.1 什么是FFmpeg 2.2 FFmpeg主要功能 2.3 使用Xabe.FFmpeg调用FFmpeg功能 2.4 使用 FFmpeg 的 drawbox 滤镜来绘制 ROI 三、总结 一、目的 当前市场上有很多目标检测智能识别的相关算法,当前调用一个医疗行业的AI识别算法后返回…...
