ThreadLocal線程本地變量在dubbo服務使用時候遇到的一個坑

我昨天遇到一個問題,就是我springboot項目里面有一個提供代辦服務審核的dubbo接口,這個接口給房源項目調用,但是碰到一個問題就是,房源項目每天凌晨5點會查詢滿足條件過期的數據,然后調用我這邊的代辦審核dubbo接口,將這個代辦任務變成自動拒絕

@Override
@Transactional
public WorkListDataResult auditWorkList(WorkListAuditCmd workListAuditCmd, WorkListLoginUserVo loginUserVo) {log.info("auditWorkList WorkListAuditCmd={},WorkListLoginUserVo={}", JSON.toJSONString(workListAuditCmd), JSON.toJSONString(loginUserVo));LoginUserUtil.setCurrentUser(loginUserVo);WorkListAuditAdapterCmd workListAuditAdapterCmd = AutoMapper.transform(WorkListAuditAdapterCmd.class, workListAuditCmd);workListAuditAdapterCmd.setAuditComments(AuditStatusEnum.PASS.getCode().equals(workListAuditCmd.getAuditStatus()) || AuditStatusEnum.PENDING_REEVALUATION.getCode().equals(workListAuditCmd.getAuditStatus()) ? "系統通過" : "系統拒絕");workListAuditAdapterCmd.setExtAuditComments(workListAuditAdapterCmd.getAuditComments());auditWorkListInternal(workListAuditAdapterCmd);WorkListAuditReq workListAuditReq = AutoMapper.transform(WorkListAuditReq.class, workListAuditCmd);Boolean needCallback = workListAuditAdapterCmd.getNeedCallback();if (needCallback != null && needCallback) {//如果dubbo接口里面參數需要回調則回調// 注冊事務同步器,在事務提交后執行異步任務TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {@Overridepublic void afterCommit() {// 確保數據提交后執行異步任務CompletableFuture.runAsync(() -> pushAuditResultToBusiness(workListAuditReq), threadPoolExecutor);}});}return new WorkListDataResult();
}

這個定時任務調用這個rpc接口時候,第二個參數WorkListLoginUserVo是傳的null,這里到后面審核的時候會根據這個 LoginUserUtil.getCurrentUser 判斷不為空,就不會進入權限校驗的邏輯

protected void auditMultiProcessWorkTaskInternal(WorkListAuditAdapterCmd workListAuditAdapterCmd) {log.info("auditMultiProcessWorkTaskInternal WorkListAuditAdapterCmd={}",JSON.toJSONString(workListAuditAdapterCmd));//校驗是否有審核的WorkListRespVo workListInfo = workListQueryService.getWorkListInfoByKeyId(workListAuditAdapterCmd.getWorkListKeyId());setAuditInfo(workListAuditAdapterCmd);Integer auditStatus = workListInfo.getAuditStatus();LoginUser currentUser = Identify.getCurrentUser();if(AuditStatusEnum.PENDING_REVIEW.getCode().equals(auditStatus)){workListAuditAdapterCmd.setFirstAuditDeptKeyId(currentUser == null ? workListAuditAdapterCmd.getAuditDeptKeyId() : currentUser.getDepartmentKeyId());workListAuditAdapterCmd.setFirstAuditUserKeyId(currentUser == null ? workListAuditAdapterCmd.getAuditUserKeyId() : currentUser.getUserKeyId());workListAuditAdapterCmd.setAuditStatus(AuditStatusEnum.PASS.getCode().equals(workListAuditAdapterCmd.getAuditStatus()) || AuditStatusEnum.PENDING_REEVALUATION.getCode().equals(workListAuditAdapterCmd.getAuditStatus()) ? AuditStatusEnum.PENDING_REEVALUATION.getCode() : AuditStatusEnum.REFUSE.getCode());workListAuditAdapterCmd.setFirstAuditTime(LocalDateTime.now());}else {workListAuditAdapterCmd.setSecondAuditUserKeyId(currentUser == null ? workListAuditAdapterCmd.getAuditUserKeyId() : currentUser.getUserKeyId());workListAuditAdapterCmd.setSecondAuditDeptKeyId(currentUser == null ? workListAuditAdapterCmd.getAuditDeptKeyId() : currentUser.getDepartmentKeyId());workListAuditAdapterCmd.setSecondAuditTime(LocalDateTime.now());workListAuditAdapterCmd.setFirstAuditTime(null);workListAuditAdapterCmd.setFirstAuditDeptKeyId(null);workListAuditAdapterCmd.setFirstAuditUserKeyId(null);}log.info("auditMultiProcessWorkTaskInternal WorkListAuditAdapterCmd={},WorkListRespVo={}",JSON.toJSONString(workListAuditAdapterCmd),JSON.toJSONString(workListInfo));// 獲取權限代碼setPermissionCode(workListAuditAdapterCmd, workListInfo);//校驗是否有審核權限,排除房源定時Job調用的情況if(currentUser != null && StringUtils.isNotBlank(currentUser.getUserKeyId()) && StringUtils.isNotBlank(currentUser.getRoleKeyId())){checkAuditPermission(currentUser,workListAuditAdapterCmd,workListInfo);}//更新代辦任務數據updateWorkList(workListAuditAdapterCmd);
}

生產上面卻發現了一個問題,就是有一定概率會有些數據進行了權限校驗,也就是currentUser不為空了,后面跟蹤房源那邊代碼才發現,那邊調用這個審核的dubbo接口,會調用另外一個查詢的rpc接口,

public WorkListDataResult<List<WorkListRespDto>> getWorkListStatusByCondion(WorkListStatusReq req, WorkListLoginUserVo loginUserVo) {log.info("getWorkListStatusByCondion WorkListStatusReq={},WorkListLoginUserVo={}", JSON.toJSONString(req), JSON.toJSONString(loginUserVo));LoginUserUtil.setCurrentUser(loginUserVo);WorkListDataResult<List<WorkListRespDto>> result = new WorkListDataResult<>();if (StringUtils.isBlank(req.getApplyType())) {result.setFlag(false);result.setErrorMessage("待辦類型不能為空!");return result;}if (StringUtils.isBlank(req.getPropertyKeyId())) {result.setFlag(false);result.setErrorMessage("房源ID不能為空!");return result;}List<WorkListRespDto> listResps = new ArrayList<>();List<UserByIdOrNumberRpcDto> userList = new ArrayList<>();//用于存放用戶ID的集合List<String> userKeyIdList = new ArrayList<>();List<DepartmentByIdOrNoRpcDto> deptList = new ArrayList<>();//用于存放部門ID的集合List<String> deptIdList = new ArrayList<>();//將空值置為nullSpringBeanUtil.convertEmptyToNull(req);WorkListSearchVo workListSearchVo = AutoMapper.transform(WorkListSearchVo.class, req);log.info("getWorkListStatusByCondion WorkListSearchVo={}", JSON.toJSONString(workListSearchVo));List<WorkListRespVo> list = workListQueryService.getWorkListStatusByCondion(workListSearchVo);log.info("getWorkListStatusByCondion list.total=" + list.size());if (list != null && list.size() > 0) {for (WorkListRespVo viewResp : list) {if (viewResp != null) {//設置userId和deptId集合setDeptOrUserList(viewResp, userKeyIdList, deptIdList);}}if (userKeyIdList != null && userKeyIdList.size() > 0) {//批量查詢用戶信息userList = userAndDeptDubboService.queryUserByIdOrNumber(userKeyIdList);log.info("getWorkListStatusByCondion userList={}", userList.toString());}if (deptIdList != null && deptIdList.size() > 0) {//批量查詢部門信息deptList = userAndDeptDubboService.queryByKeyIdOrNo(deptIdList);log.info("getWorkListStatusByCondion deptList={}", deptList.toString());}for (WorkListRespVo viewResp : list) {//設置枚舉描述setWorkListVoDesc(viewResp);//設置待辦對象用戶和部門信息setWorkListRespVoDeptOrUser(viewResp, userList, deptList);WorkListRespDto workListRespVo = AutoMapper.transform(WorkListRespDto.class, viewResp);listResps.add(workListRespVo);}}result.setFlag(true);result.setData(listResps);return result;
}

這個查詢的接口也進行了LoginUserUtil.setCurrentUser(loginUserVo),這段代碼會放到ThreadLocal 的線程本地變量里面

而整個這個查詢和審核的接口都沒有進行這個ThreadLocal線程變量的清除,因為dubbo提供的rpc接口,本質上是使用了線程池技術,會復用一些線程,比如說19號先執行了這個查詢代辦任務的rpc接口,這個時候設置了currentUser,然后后面調用這個代辦審核的接口時候,又剛好拿到了這個19號線程,這個時候通過getCuurentUser拿到的用戶就不為空,然后就進入了權限校驗的邏輯,解決辦法通過自定義dubbo的過濾器,在過濾器里面完成資源的清除

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/907025.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/907025.shtml
英文地址,請注明出處:http://en.pswp.cn/news/907025.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

[Java實戰]Spring Boot整合達夢數據庫連接池配置(三十四)

[Java實戰]Spring Boot整合達夢數據庫連接池配置&#xff08;三十四&#xff09; 一、HikariCP連接池配置&#xff08;默認&#xff09; 1. 基礎配置&#xff08;application.yml&#xff09; spring:datasource:driver-class-name: dm.jdbc.driver.DmDriverurl: jdbc:dm://…

【MySQL】08.視圖

視圖就是一個由查詢到的內容定義的虛擬表。它和真實的表一樣&#xff0c;視圖包含一系列帶有名稱的列和行數據。視圖的數據變化會影響到基表&#xff0c;基表的數據變化也會影響到視圖。 1. 基本使用 mysql> select * from user; -------------------- | id | age | name …

4 通道1250MSPS‐16bit DAC 回放板

簡介 4 通道1250MSPS‐16bit DAC 回放板 是一款4 路轉換速率最高為1250MSPS 的DAC 回放板&#xff0c; DAC 位數16bit&#xff1b;板卡支持觸發輸出/觸發輸入&#xff1b;DAC 采樣時鐘源支持內部參考時 鐘、外部參考時鐘、外部采樣時鐘三種方式&#xff0c;可通過SPI 總線實現時…

C/C++---類型轉換運算符

在C中&#xff0c;類型轉換運算符&#xff08;Type Conversion Operator&#xff09;允許類對象在需要時自動轉換為其他類型。這是一種特殊的成員函數&#xff0c;能夠增強類的靈活性和交互性。 1. 基本語法 類型轉換運算符的聲明格式為&#xff1a; operator 目標類型() co…

大模型Agent

手撕 Agent 1、功能描述 設計一個 Agent,自動選擇使用以下工具回答用戶的問題: 查看目錄下的文件基于給定的文檔回答用戶問題查看與分析 Excel 文件撰寫文檔調用 Email 客戶端發郵件2、演示用例 實驗中使用三個文檔演示 Agent 的能力 ./data|__2023年8月-9月銷售記錄.xlsx…

超臨界機組協調控制系統建模項目開發筆記

超臨界機組協調控制系統建模項目開發筆記 項目概述 本項目基于兩篇論文的方法&#xff0c;對超臨界機組協調控制系統進行數據驅動建模。主要使用LSTMTransformer混合架構&#xff0c;實現對主蒸汽壓力(Pst)、分離器蒸汽焓值(hm)和機組負荷(Ne)的預測。同時&#xff0c;通過消…

mysql安全管理

數據庫管理系統用于管理數據庫服務器的各種數據庫資源&#xff0c;MYSQL是一個支持多用戶的數據庫管理系統&#xff0c;實現多用戶下&#xff0c;各種數據庫資源的安全訪問控制&#xff0c;確保數據庫資源安全訪問成為了數據庫管理系統的核心功能。MYSQL安全管理是指允許合法賬…

QT中常用的類

Qt 是一個功能強大的跨平臺框架&#xff0c;提供了豐富的類庫來開發 GUI 和應用程序。以下是 ??Qt 中常用的核心類??&#xff0c;按模塊分類整理&#xff1a; ??1. GUI 和窗口管理?? 類名用途示例場景??QWidget??所有 GUI 控件的基類&#xff08;按鈕、窗口等&…

【Redis原理篇】五大基本數據類型的底層編碼方式

上文&#xff1a;redis底層數據結構 String底層結構 一、編碼方式 1.int編碼 **適用范圍&#xff1a;**64位整數&#xff08;long&#xff09; **實現&#xff1a;**直接將數據存儲在redisObject的ptr指針位置。 內存布局&#xff1a; 2.embstr編碼 **適用條件&#xf…

自動編碼器 潛在空間 Autoencoders 視頻截圖

【雙語】Autoencoders_嗶哩嗶哩_bilibili 【雙語】Autoencoders_嗶哩嗶哩_bilibili

ZLG USBCANFD python UDS刷寫腳本

文章目錄 概述python UDS 刷寫腳本UI交互界面概述 在實際工作中,有使用周立功的UDSCANFD設備,用來收發CAN數據和UDS on CAN的診斷測試或者UDS on CAN的ECU升級。上位機使用ZCANPro,軟件自帶ECU刷新界面,可以編輯UDS服務,加載升級文件等,能用是能用,但是仍不能滿足一些特…

線程安全問題的成因

前言 大家晚上好呀~~ 今天學習了線程不安全問題的成因。線程安全問題是十分重要的知識點&#xff0c;我想把我所學的與大家分享一波&#xff0c;希望可以幫助到有需要的人&#xff0c;同時加深自己對于線程安全問題的理解。 分析過程如下 結語 今天心情還不錯~ 要堅持持續…

C++可變參數宏定義語法筆記

1. 基礎語法 定義格式&#xff1a; #define MACRO_NAME(fixed_args, ...) macro_body#define LOG(fmt, ...) printf(fmt, __VA_ARGS__) LOG("Value: %d, Name: %s", 42, "Alice"); // 展開為 printf("Value: %d, Name: %s", 42, "Alice&q…

mongodb安裝啟動

這里寫自定義目錄標題 安裝包下載安裝后文件目錄列表bin目錄下 mongod 可以對mongodb 進行啟動等操作 環境變量配置創建數據目錄&#xff0c;日志目錄啟動參數配置啟動 mongodbweb頁面訪問&#xff0c;檢查服務啟動是否正常可視化工具連接mongodb創建 database創建collection查…

Leetcode 3562. Maximum Profit from Trading Stocks with Discounts

Leetcode 3562. Maximum Profit from Trading Stocks with Discounts 1. 解題思路2. 代碼實現 題目鏈接&#xff1a;3562. Maximum Profit from Trading Stocks with Discounts 1. 解題思路 這一題沒有搞定&#xff0c;思路上整體走偏了&#xff0c;看了一下別人的解答&…

【Redis】第2節|Redis基本數據類型

一、基礎數據結構 1. String&#xff08;字符串&#xff09; 特點&#xff1a;二進制安全&#xff0c;支持字符串、數值存儲&#xff0c;原子性操作。核心操作&#xff1a; SET key value # 存儲鍵值對 GET key # 獲取值 INCR key # 數值…

用matlab提取abaqus odb文件中的節點信息

在MATLAB中提取Abaqus ODB文件中的節點信息&#xff0c;可以通過以下幾種方法實現&#xff1a; 方法1&#xff1a;使用MATLAB的ABAQUS Interface工具箱 https://wenku.csdn.net/answer/77axwtqnys 可以參考這個 MATLAB的ABAQUS Interface工具箱提供了直接讀取ODB文件的功能。…

【Java】異常處理

1.異常的概念 在程序運行時&#xff0c;打斷正常程序流程的不正常情況分兩類: 1.錯誤(Error)&#xff1a;應用程序無法捕獲的嚴重問題(自己無法處理) 例&#xff1a; 虛擬機相關的問題&#xff0c;如虛擬機崩潰、動態鏈接失敗、低層資源錯誤等 總是不受編譯器檢查的&#xff0…

Linux(Centos 7.6)命令詳解:tar

1.命令作用 命令tar將許多文件一起保存到單個磁帶或磁盤存檔中&#xff0c;并且可以從存檔中恢復單個文件(GNU tar saves many files together into a single tape or disk archive, and can restore individual files from the archive.)。 2.命令語法 Usage: tar [OPTION.…

企業網絡綜合實訓

企業網絡綜合實訓 任務描述&#xff1a; 公司的中心機房、辦公區一和辦公區二位于同一園區。要求各大樓之間要互通&#xff0c;并且均能訪問Internet&#xff1b;同時公司業務需要對外拓展&#xff0c;需要在Internet數據中心機房部署一臺對外提供DNS和Web站點服務的服務器。…