Sa-Token 在 @Async 和定时任务等异步上下文调用 StpUtil 报 SaTokenContextException 怎么解决?
Sa-Token 在 Async 和定时任务等异步上下文调用 StpUtil 报 SaTokenContextException 怎么解决【免费下载链接】Sa-Token✨ 开源、免费、一站式 Java 权限认证框架让鉴权变得简单、优雅—— 登录认证、权限认证、分布式 Session 会话、微服务网关鉴权、SSO 单点登录、OAuth2.0 统一认证、jwt 集成、API Key 秘钥授权、API 参数签名项目地址: https://gitcode.com/GitHub_Trending/sa/Sa-Token在 Sa-Token 项目中登录认证通常发生在 Web 请求里Controller 里调用StpUtil.isLogin()、StpUtil.getLoginId()、StpUtil.getTokenValue()都能正常工作。但一旦把这些调用挪到Async标注的异步方法、Scheduled定时任务、线程池任务或 MQ 消费者里就会抛出cn.dev33.satoken.exception.SaTokenContextException: SaTokenContext 上下文尚未初始化这篇文章说明这个异常的成因并给出 Sa-Token 官方文档给出的解决方案在异步线程中用SaTokenContextMockUtil.setMockContext手动 Mock 一个上下文后再调用StpUtilAPI。仓库中的 sa-token-demo-async 示例 覆盖了Async、Scheduled、线程池、new Thread四种场景可直接对照修改和验证。为什么异步上下文会报这个异常根据文档 async--mock.mdStpUtil.isLogin()这类方法只可以在同步的 Web 上下文中调用因为它们需要从前端提交的HttpServletRequest中读取 Token 参数。而异步上下文通常不是一次请求没有HttpServletRequest的概念所以无法成功调用。文档列出的典型异步上下文包括通过new Thread(() - { ... }).start()启动子线程通过taskExecutor.execute(() - { ... })线程池启动异步任务通过Async注解标注的方法通过Scheduled(cron )启动的定时任务消息队列中消费消息的函数。凡是不通过 web 请求调用触发的线程在 Sa-Token 中均属于异步上下文也可以称作非 Web 上下文此时调用StpUtil.isLogin()、StpUtil.getLoginId()等需要 Web 上下文的 API就会抛出上述SaTokenContextException。解决方式Mock 上下文 指定 token 值文档给出的做法分两步调用SaTokenContextMockUtil.setMockContext(() - { ... })Mock 出一个 Web 上下文填充到上下文管理器中在 Mock 上下文范围内调用StpUtil.setTokenValueToStorage(tokenValue)指定当前上下文的 token 值其效果等同于在 web 上下文中前端提交了此 token 值。工具类 SaTokenContextMockUtil.java 位于sa-token-core的cn.dev33.satoken.context.mock包中带回调的setMockContext(SaFunction fun)方法会在回调执行完毕后自动清除上下文因此建议总是使用带回调的形式把需要访问StpUtil的代码都包在回调内。注意token 值必须在 Web 请求线程中提前取到例如StpUtil.getTokenValue()再传入异步任务不能指望子线程自己继承请求里的 token。Async 场景仓库示例 TestController.java 中的isLogin4方法演示了Async方法内的写法// 【异步】Async --- http://localhost:8081/test/isLogin4 Async RequestMapping(isLogin4) public SaResult isLogin4(CookieValue(satoken) String satoken) { SaTokenContextMockUtil.setMockContext(()-{ StpUtil.setTokenValueToStorage(satoken); System.out.println(是否登录 StpUtil.isLogin()); }); return SaResult.ok(); }这里satoken是从请求 Cookie 中读出的 token 值token-name: satoken见下文配置传入 Mock 上下文后再判断登录状态。如果你是在 Controller 里同步取 token 再交给异步方法处理可以先StpUtil.getTokenValue()拿到tokenValue再在异步回调里StpUtil.setTokenValueToStorage(tokenValue)。Scheduled 定时任务场景同一示例中的scheduledMethod演示了定时任务每分钟执行一次Scheduled(cron 0 * * * * ?) // 一分钟执行一次 public void scheduledMethod(){ // 错误写法直接调用 Sa-Token API 会报错 // System.out.println(定时任务Mock 范围外是否登录 StpUtil.isLogin()); System.out.println(SaFoxUtil.formatDate(new Date())); // 需要先设置模拟上下文 SaTokenContextMockUtil.setMockContext(() - { // StpUtil.setTokenValueToStorage(f452571f-bfdb-413d-aba9-e26992cf07be); // 模拟 Token System.out.println(定时任务Mock 范围内是否登录 StpUtil.isLogin()); // 模拟登录 // StpUtil.login(10066); // 模拟 登录 // System.out.println(定时任务Mock 范围内登录账号 StpUtil.getLoginId()); }); }注意示例注释明确标注在 Mock 范围外直接调用StpUtil.isLogin()会报错必须放进setMockContext回调内定时任务这种没有请求来源的场景要么用setTokenValueToStorage指定一个已知 token如示例注释中展示的固定 token 值仅为文档示例要么在 Mock 范围内直接StpUtil.login(10066)模拟登录。线程池与 new Thread 场景同文件中的isLogin3ThreadPoolTaskExecutor与isLogin2new Thread写法一致核心都是先在请求线程中StpUtil.getTokenValue()取出 token再在异步任务里 Mock// 【异步】线程池 ThreadPoolTaskExecutor --- http://localhost:8081/test/isLogin3 RequestMapping(isLogin3) public SaResult isLogin3(HttpServletRequest request, HttpServletResponse response) { System.out.println(是否登录 StpUtil.isLogin()); String tokenValue StpUtil.getTokenValue(); taskExecutor.execute(() - { SaTokenContextMockUtil.setMockContext(()-{ StpUtil.setTokenValueToStorage(tokenValue); System.out.println(是否登录 StpUtil.isLogin()); }); }); return SaResult.data(StpUtil.getTokenValue()); }按仓库示例验证示例项目位于 sa-token-demo-async验证前提来自该项目的配置文件启动类 SaTokenAsyncApplication.java 上标注了EnableAsync启用异步和EnableScheduling启动定时任务你的项目要使用Async/Scheduled也需要具备相应注解。application.yml 中服务端口为8081token-name: satoken并配置了127.0.0.1:6379的 Redis 连接如果照示例运行需要本地有可用 Redis。验证步骤示例中的访问路径来自代码注释启动sa-token-demo-async先访问http://localhost:8081/test/login?id10001完成登录带 token 访问http://localhost:8081/test/isLogin4Async场景或http://localhost:8081/test/isLogin3线程池场景观察控制台输出修复前异步线程中直接调用StpUtil.isLogin()会抛出SaTokenContextException按上述方式 Mock 后控制台会打印是否登录的判断结果且不再抛出该异常。定时任务场景则等待下一个整分钟0 * * * * ?观察控制台打印定时任务Mock 范围内是否登录...而不是抛出异常。限制与注意事项不要依赖InheritableThreadLocal传递上下文。示例 TestController.java 文末的注释记录了这个坑子线程虽然能读到 request但 SpringBoot 在请求结束后会清除 request 里的数据导致代码能成功运行、但逻辑错误的隐形 bug例如子线程先 sleep 一秒再取值结果从 true 变成 false。官方结论是应该避免使用InheritableThreadLocal存储上下文数据而应显式 Mock。Mock 范围只包住回调内的代码。setMockContext(fun)执行完会clearContext()把StpUtil调用放在回调外仍会报原异常。本文针对的是 ServletHttpServletRequest体系项目。若在 WebFlux 等响应式环境中出现同名异常文档给出的是另一套处理方式SaReactorSyncHolder.setContext(exchange)后再调用同步 API并在 finally 中清除见 async--mock.md 的响应式上下文一节。完成上述修改后Async方法与定时任务中即可按Mock 上下文 → 指定 token → 调用 StpUtil API的固定路径访问登录态不再出现SaTokenContextException: SaTokenContext 上下文尚未初始化。【免费下载链接】Sa-Token✨ 开源、免费、一站式 Java 权限认证框架让鉴权变得简单、优雅—— 登录认证、权限认证、分布式 Session 会话、微服务网关鉴权、SSO 单点登录、OAuth2.0 统一认证、jwt 集成、API Key 秘钥授权、API 参数签名项目地址: https://gitcode.com/GitHub_Trending/sa/Sa-Token创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

全国省级11级卫星影像下载全攻略:从切片规则到拼接制图

全国省级11级卫星影像下载全攻略:从切片规则到拼接制图

这个标题我看着很眼熟。很多人第一次接触“全国各省份影像下载地址(11级)”这种说法,会一头雾水,以为是个可以直接点开的链接仓库。实际接触过地理数据的人一下就明白了,这里说的是卫星影像数据,而且特指地…

2026/11/10 7:51:47 阅读更多 →
copilot.vim 实战指南:在 Vim/Neovim 中配置与使用 GitHub Copilot

copilot.vim 实战指南:在 Vim/Neovim 中配置与使用 GitHub Copilot

copilot.vim 实战指南:在 Vim/Neovim 中配置与使用 GitHub Copilot 【免费下载链接】copilot.vim Neovim plugin for GitHub Copilot 项目地址: https://gitcode.com/GitHub_Trending/co/copilot.vim 本指南以 copilot.vim 插件的官方 README.md 为骨架&…

2026/10/22 12:05:12 阅读更多 →
Automatisch 核心概念详解:App、Connection、Flow 与 Step

Automatisch 核心概念详解:App、Connection、Flow 与 Step

Automatisch 核心概念详解:App、Connection、Flow 与 Step 【免费下载链接】automatisch The open source Zapier alternative. Build workflow automation without spending time and money. 项目地址: https://gitcode.com/GitHub_Trending/au/automatisch …

2026/10/24 1:38:41 阅读更多 →

最新新闻

Electron桌面应用开发实战:从环境搭建到打包发布全流程

Electron桌面应用开发实战:从环境搭建到打包发布全流程

做前端这些年,我大部分时间都在跟浏览器标签页打交道,直到第一次把桌面应用跑起来,才发现原来自己一直被限制在地址栏和刷新按钮围起来的框框里。Electron这个词,最开始是在某段时间频繁出现在同事的讨论里,一个用HTML…

2026/11/9 14:01:10 阅读更多 →
滑盖智能锁T109深度解析:结构原理、安装调试与故障排查

滑盖智能锁T109深度解析:结构原理、安装调试与故障排查

简介:亚太天能T109滑盖智能锁产品说明书是一份PDF格式的官方技术文档,主要面向智能锁安装人员、终端用户及售后维护者,帮助快速掌握产品安装、配置与常见故障处理。全包仅1个PDF文件,大小4.37MB,内容结构清晰&#xff…

2026/11/9 14:56:39 阅读更多 →
PMSM弱磁控制原理与Simulink建模:高速AGV驱动系统设计指南

PMSM弱磁控制原理与Simulink建模:高速AGV驱动系统设计指南

上个月我在调试一台高速AGV的驱动系统,整车要求空载跑到8m/s,电机转速已经拉到额定点,驱动器的输出电压也顶到了母线电压极限附近。再往上踩速度指令,转速纹丝不动,三相电流反而开始震荡。那会儿我的第一反应就是&…

2026/11/10 2:03:25 阅读更多 →
C++核心知识点:从内存管理到STL的实战指南

C++核心知识点:从内存管理到STL的实战指南

C 这门语言我前前后后折腾了十几年,用它写过嵌入式驱动、做过游戏服务端,也搭过基础组件库。每次看到新人一头扎进"C 核心知识点"这个搜索词,我其实挺感慨的——这门语言的难点从来不是语法多,而是知识点之间的耦合太深…

2026/11/9 14:01:10 阅读更多 →
T109滑盖智能锁怎么装?安装调试与故障排查全攻略

T109滑盖智能锁怎么装?安装调试与故障排查全攻略

简介:亚太天能T109滑盖智能锁产品说明书以PDF格式发布,适合智能锁用户、安装人员与售后维修人员阅读。内容围绕T109系列指纹密码刷卡锁展开,先介绍前面板、后面板、锁体、机械钥匙、电池盒盖等部件名称与功能,再给出完整安装步骤&…

2026/11/9 7:45:06 阅读更多 →
LLM知识降熵:从信息垄断到理解权下放

LLM知识降熵:从信息垄断到理解权下放

你有没有过这种经历:翻开源码注释、论文摘要或者一份专业报告,每个字都认识,连在一起却像天书。想找人聊聊,身边要么没人懂,要么懂的懒得跟你解释。后来我试着把同一段内容丢给一个大语言模型,几秒钟之后&a…

2026/11/9 14:01:11 阅读更多 →

日新闻

周新闻

月新闻