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

spring监听请求执行结束,移除当前ThreadLocal数据两种方法

在开发过程中,很多时候我们会使用ThreadLocal来临时缓存数据,当一次数据请求执行完成后需要主动执行释放当前ThreadLocal缓存数据资源,防止未能及时释放导致下一次访问时候ThreadLocal依然保持上一次缓存的数据。

spring提供两种方式去监听一次请求完成事件。
1、HandlerInterceptor -> afterCompletion 使用拦截方式,再执行完成后执行afterCompletion
2、ApplicationListener -> ServletRequestHandledEvent ,ApplicationListener 提供的是监听那种事件类型,ServletRequestHandledEvent 就是一次请求结束后的事件。

通过上述两种方式可以很方便的在一次请求完成移除当前线程ThreadLocal。

ThreadLocal 工具

public class ThreadLocal2UserSessionUtil {

    private static final ThreadLocal<Object> LOCAL = new ThreadLocal<>();

    /**
     * 设置数据
     *
     * @param paramMap
     */
    public static void set(Map<String, Object> paramMap) {
        LOCAL.set(paramMap);
    }

    /**
     * 获取值
     *
     * @return
     */
    public static Map<String, Object> get() {
        if (Objects.isNull(LOCAL.get())) {
            return new HashMap<>();
        } else {
            return (Map<String, Object>) LOCAL.get();
        }
    }

    /**
     * 获取值
     *
     * @return
     */
    public static Object get(String key) {
        Map<String, Object> resMap = (Map<String, Object>) LOCAL.get();
        if (null == resMap) {
            return null;
        }
        return (null != resMap.get(key)) ? resMap.get(key) : null;
    }

    /**
     * 每次取出数据后必须清空 否则就会出现值重复
     */
    public static void remove() {
        LOCAL.remove();
    }

    /**
     * 获取app登录token
     *
     * @return
     */
    public static String getToken4App() {
        Map<String, Object> map = get();
        return (null == map) ? "" : (String) map.get(EncryptReqParamNameConstant.PARAM_TOKEN);
    }

    /**
     * 初始化数值
     *
     * @return
     */
    public static void pushUserToken4App(String appToken) {
        Map<String, Object> localMap = get();
        if (StringUtil.isNotBlank(appToken)) {
            localMap.put(EncryptReqParamNameConstant.PARAM_TOKEN, appToken);
            set(localMap);
        }
    }

    /**
     * 初始化数值
     *
     * @return
     */
    public static void pushUserId4App(Long userId) {
        Map<String, Object> localMap = get();
        if (null != userId) {
            localMap.put(EncryptReqParamNameConstant.USER_ID, userId);
            set(localMap);
        }
    }


    /**
     * 初始化数值  注意这里只有加解密才将用户id放入
     *
     * @return
     */
    public static Long getUserId4App() {
        Map<String, Object> map = get();
        return (null == map) ? null : (Long) map.get(EncryptReqParamNameConstant.USER_ID);
    }
}

HandlerInterceptor 方式

@Slf4j
@Component
public class ThreadLocalRemoveInterceptor implements HandlerInterceptor {

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
        ThreadLocal2UserSessionUtil.remove();
    }
}

在web控制器中加入监听器

@Configuration
public class PathPrefixMvcConfigurer implements WebMvcConfigurer {

    @Autowired
    private ThreadLocalRemoveInterceptor threadLocalRemoveInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(threadLocalRemoveInterceptor).addPathPatterns("/*");
    }
}

2、通过监听器方式

@Slf4j
@Component
public class ServletRequestHandledEventListener implements ApplicationListener<ServletRequestHandledEvent> {

    @Override
    public void onApplicationEvent(ServletRequestHandledEvent event) {
      ThreadLocal2UserSessionUtil.remove();
    }
}

完成


http://www.kler.cn/a/106402.html

相关文章:

  • 什么是Spring Boot Actuator
  • FreeSWITCH chat 得到的是 Error! Message Not Sent
  • 创建vue+electron项目流程
  • 单元测试、集成测试、系统测试、验收测试、压力测试、性能测试、安全性测试、兼容性测试、回归测试(超详细的分类介绍及教学)
  • 阿里云ACK容器如何配置pod分散在集群的不同节点上
  • thinkphp6配置多应用项目及多域名访问路由app配置
  • CFD模拟仿真理论知识:流体仿真应用
  • tmux和vim
  • InstructionGPT
  • Chimera:混合的 RLWE-FHE 方案
  • dto参数校验及统一异常处理
  • 分组卷积的思想神了
  • Autojs 利用OpenCV识别棋子之天天象棋你马没了
  • vue列表导出word文档
  • pre标签变成可以编辑的状态
  • 国产CAN总线收发芯片DP1042 兼容替换TJA1042
  • Linux 云服务器磁盘挂载简介
  • Transit path
  • SpringMVC原理及核心组件
  • 【大数据 - Doris 实践】数据表的基本使用(五):ROLLUP
  • MODBUS-TCP通信客户端如何访问服务器端RS485总线上的从站(SMART PLC梯形图程序)
  • 服务网络基础
  • 构造类型详解及热门题型结构体大小的计算
  • [Pytorch] 保存模型与加载模型
  • Leetcode 49. 字母异位词分组
  • 我是如何走上测试管理岗的