• Springboot——使用ThreadLocal进行请求前后参数数据传递


    简介

    ThreadLocal叫做线程变量,意思是ThreadLocal中填充的变量属于当前线程,该变量对其他线程而言是隔离的,也就是说该变量是当前线程独有的变量。ThreadLocal为变量在每个线程中都创建了一个副本,那么每个线程可以访问自己内部的副本变量。

    ThreadLoal 变量,线程局部变量,同一个 ThreadLocal 所包含的对象,在不同的 Thread 中有不同的副本。这里有几点需要注意:

    • 因为每个 Thread 内有自己的实例副本,且该副本只能由当前 Thread 使用。这是也是 ThreadLocal 命名的由来。
    • 既然每个 Thread 有自己的实例副本,且其它 Thread 不可访问,那就不存在多线程间共享的问题

    ThreadLocal 提供了线程本地的实例。它与普通变量的区别在于,每个使用该变量的线程都会初始化一个完全独立的实例副本。ThreadLocal 变量通常被private static修饰。当一个线程结束时,它所使用的所有 ThreadLocal 相对的实例副本都可被回收。

    总的来说,ThreadLocal 适用于每个线程需要自己独立的实例且该实例需要在多个方法中被使用,也即变量在线程间隔离而在方法或类间共享的场景

    下图可以增强理解:

    在这里插入图片描述

    简介摘选 史上最全ThreadLocal 详解

    结合Springboot使用

    通常为了减少校验业务频繁查询数据库使用。

    定义MyThreadLocal

    /**
     * 单实例
     */
    public class MyThreadLocal {
    
        private MyThreadLocal() {
        }
    
        private static final ThreadLocal<String> threadLocal = new ThreadLocal<String>();
    
        /**
         * 对当前线程中的map域设置属性值,不会对其他线程产生影响  Thread.currentThread()
         * @param str
         */
        public static void set(String str){
            threadLocal.set(str);
        }
    
        public static String get(){
            return threadLocal.get();
        }
    
        /**
         * 本质上是调用当前线程的remove,不会对其他线程产生影响
         */
        public static void remove(){
            threadLocal.remove();
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    定义拦截处理器

    package com.nstc.bi.config.base;
    
    import org.springframework.stereotype.Component;
    import org.springframework.web.servlet.HandlerInterceptor;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    @Component
    public class BaseInterceptor implements HandlerInterceptor {
        private Logger log = LoggerFactory.getLogger(BaseInterceptor.class);
    
        /**
         * 请求处理前
         * @param request
         * @param response
         * @param handler
         * @return
         * @throws Exception
         */
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            // 获取请求头中的 单位编号 信息
            String userCltNo = request.getHeader("key");
            log.info("-----preHandle----userCltNo---{}",userCltNo);
            MyThreadLocal.set(userCltNo);
            return true;
        }
    
        /**
         * 请求处理后
         * @param request
         * @param response
         * @param handler
         * @param ex
         * @throws Exception
         */
        @Override
        public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
            // 请求完后,需要清空 MyThreadLocal 集合数据
            // 避免 OOM
            MyThreadLocal.remove();
            log.info("-----afterCompletion----MyThreadLocal.remove()");
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48

    定义指定请求拦截过滤

    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
    import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
    
    @Configuration
    public class InterceptorConfig implements WebMvcConfigurer {
    
        @Autowired
        private BaseInterceptor baseInterceptor;
    
        /**
         * 针对所有的请求,增加一个获取header数据的解析
         * @param registry
         */
        @Override
        public void addInterceptors(InterceptorRegistry registry) {
            registry.addInterceptor(baseInterceptor).addPathPatterns("/**");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
  • 相关阅读:
    MySQL数据库——17.正则表达式
    javaScript语法
    【微服务】 微服务学习笔记二:Eureka注册中心的介绍及搭建
    SAP S4后的一些注意点(一)(更新中)
    Go语言内置函数、标准库、常用工具命令
    《Spring实战(第四版)》pdf
    前端 CSS 经典:边框转圈动画效果
    是谁在Go标准库的源码中植入了色情网站?
    MAX17058_MAX17059 STM32 iic 驱动设计
    【算法设计技巧】贪婪算法与回溯算法
  • 原文地址:https://blog.csdn.net/qq_38322527/article/details/126032556