【已解决-实操篇】SaTokenException: 非Web上下文无法获取Request问题解决-实操篇

  • 作者: 凯哥Java(公众号:凯哥Java)
  • sa-token
  • 时间:2023-11-07 14:29
  • 2809人已阅读
简介 在上一篇《【理论篇】SaTokenException:非Web上下文无法获取Request问题解决-理论篇》中,凯哥(公众号:凯哥Java)介绍了了产生这个问题的源码在哪里,以及怎么解决的方案。没有给出实际操作步骤。本文,凯哥就通过threadLocal方案来解决。一、创建用于存放共享变量的对象代码如下:package com.kaigejava.dataanalysis;import&

🔔🔔🔔好消息!好消息!🔔🔔🔔

有需要的朋友👉:联系凯哥 微信号 kaigejava2022

在上一篇《【理论篇】SaTokenException: 非Web上下文无法获取Request问题解决 -理论篇》中,凯哥(公众号:凯哥Java)介绍了产生这个问题的源码在哪里,以及怎么解决的方案。没有给出实际操作步骤。

本文,凯哥就通过threadLocal方案来解决。

一、创建用于存放共享变量的对象

代码如下:

package com.kaigejava.dataanalysis;

import lombok.Data;
import lombok.extern.slf4j.Slf4j;
@Data
@Slf4j
public class ThreadShareDataDTO {

    /**
     * 是否拥有数据查看权限。
     * 用来解决:SaToken,非Web上下文无法获取Request问题的
     */
    private Boolean hasDataViewRole;
    //防止new,生成单例类
    private ThreadShareDataDTO(){}
    /**
     * ThreadLocal:将变量与当前线程绑定,相当于Map<Thread, value>
     * 此处使用的是饱汉模式构造
     */
    private static ThreadLocal<ThreadShareDataDTO> threadLocal = new ThreadLocal<>();
    /**
     * 返回当前线程的单例
     * 此处不需要使用关键字synchronized,想想为什么?
     */
    public static ThreadShareDataDTO getCurrentThreadInstance() {
        ThreadShareDataDTO shareData = threadLocal.get();
        if (shareData == null) {
            shareData = new ThreadShareDataDTO();
            threadLocal.set(shareData);
        }
        return shareData;
    }


    public static void clear(){
        log.info("开始移除threadLocal中数据");
        threadLocal.remove();
    }

}


二、在开启子线程的时候,将需要传递的参数设置到threadLocal中

public void startCreateDataReport(TenantMonitorReportListRequest param) {
    boolean hasDataViewRole = StpUtil.hasRole(dataViewRole);
    param.setHasDataViewRole(hasDataViewRole);
   new  MakeReportThread(param).start();
  
}


三、在子线程中获取到共享变量

boolean hasDataViewRole ;
ThreadShareDataDTO shardData = ThreadShareDataDTO.getCurrentThreadInstance();
if (Objects.nonNull(shardData.getHasDataViewRole())) {
    hasDataViewRole = shardData.getHasDataViewRole();
} else {
    hasDataViewRole = StpUtil.hasRole(dataViewRole);
}

说明:

先从threadLocal中获取共享变量,如果存在,就直接获取。如果不存在在调用原来的方法。


四、使用完成之后,已经要记得remove掉

在线程执行完成之后,finally方法中移除:

} finally {
 
    //从threadLocal中移除
    ThreadShareDataDTO.clear();
}


TopTop