码农知识堂 - 1000bd
  •   Python
  •   PHP
  •   JS/TS
  •   JAVA
  •   C/C++
  •   C#
  •   GO
  •   Kotlin
  •   Swift
  • springboot自定义使用threadLocal


    定义

    java中ThreadLocal的使用

    ThreadLocal主要用来为当前线程存储数据,这个数据只有当前线程可以访问。可以将ThreadLocal看成是一个map,而当前的线程就是map中的key。

    下面是ThreadLocal的类图结构,从图中可知:Thread类中有两个变量threadLocals和inheritableThreadLocals,二者都是ThreadLocal内部类ThreadLocalMap类型的变量,我们通过查看内部内ThreadLocalMap可以发现实际上它类似于一个HashMap。在默认情况下,每个线程中的这两个变量都为null,只有当线程第一次调用ThreadLocal的set或者get方法的时候才会创建他们(后面我们会查看这两个方法的源码)。除此之外,和我所想的不同的是,每个线程的本地变量不是存放在ThreadLocal实例中,而是放在调用线程的ThreadLocals变量里面(前面也说过,该变量是Thread类的变量)。也就是说,ThreadLocal类型的本地变量是存放在具体的线程空间上,其本身相当于一个装载本地变量的工具壳,通过set方法将value添加到调用线程的threadLocals中,当调用线程调用get方法时候能够从它的threadLocals中取出变量。如果调用线程一直不终止,那么这个本地变量将会一直存放在他的threadLocals中,所以不使用本地变量的时候需要调用remove方法将threadLocals中删除不用的本地变量。

    在这里插入图片描述

    配置自定义ThreadLocal

    在拦截器或者过滤器中set完之后再请求完成之后一定要remove,不然可能会数据错乱

    package com.felix.spring_cloud_one.threadLocal;
    
    /**
     * @author fchen
     */
    public class RequestContext {
    
        private final static ThreadLocal my = ThreadLocal.withInitial(() -> new Object());
    
        public static void set(Object data){
            my.set(data);
        }
    
        public static Object get(){
            return my.get();
        }
    
        public static void remove(){
            my.remove();
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    配置拦截器

    当请求url错误的时候,比如404,此时会进入两次重写的preHandle方法,因为第一次请求发现404后会转到/error路径

    package com.felix.spring_cloud_one.threadLocal.config;
    
    import com.fasterxml.jackson.databind.ObjectMapper;
    import com.felix.spring_cloud_one.threadLocal.RequestContext;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Component;
    import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.util.HashMap;
    import java.util.Map;
    import java.util.Objects;
    import java.util.concurrent.atomic.AtomicInteger;
    
    /**
     * @author fchen
     */
    @Component
    public class HttpInterceptor extends HandlerInterceptorAdapter {
    
        private final AtomicInteger atomicLong = new AtomicInteger(0);
    
        @Autowired
        private ObjectMapper objectMapper;
    
    	
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            System.out.println("上一次的threadLocal数据{}" + RequestContext.get().toString());
            Map map = new HashMap<>();
            map.put("currentThread", Thread.currentThread().toString());
            map.put("atomicLong", atomicLong.get());
            System.out.println("当前atomicLong: " + atomicLong.getAndIncrement());
            System.out.println("请求路径:" + request.getRequestURI());
            RequestContext.set(map);
            System.out.println("添加自定义threadLocal数据{}" + objectMapper.writeValueAsString(RequestContext.get()));
            return true;
        }
    
    
    
    
    
    
        @Override
        public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
            System.out.println("移除自定义threadLocal数据{}" + objectMapper.writeValueAsString(RequestContext.get()));
            RequestContext.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
    • 49
    • 50
    • 51

    注册拦截器

    package com.felix.spring_cloud_one.threadLocal.config;
    
    import org.springframework.beans.BeansException;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.ApplicationContextAware;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
    import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
    
    /**
     * 配置拦截器
     * @author fchen
     */
    @Configuration
    public class ThreadLocalAdapter implements WebMvcConfigurer , ApplicationContextAware {
    
        private ApplicationContext applicationContext;
    
    
        @Override
        public void addInterceptors(InterceptorRegistry registry) {
            registry
                    .addInterceptor(applicationContext.getBean(HttpInterceptor.class))
                    //拦截所有路径
                    //.addPathPatterns("/**")
                    ;
        }
    
    
        @Override
        public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
            this.applicationContext = applicationContext;
        }
    }
    
    • 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

    参考了大佬们的博客
    https://www.cnblogs.com/fsmly/p/11020641.html

  • 相关阅读:
    股票python量化交易020-双均线策略(上)
    内网渗透神器CobaltStrike之DNS Beacon(四)
    硬件工程师成长之路(10.1)——芯片选型
    BIM被捧了10多年,大部分人对其有误解
    护眼台灯横评|书客、明基、松下品牌大测评告诉你谁才是最亮的星!
    ThreadX笔记
    Gartner发布报告揭秘微软数据安全功能和许可
    Qt中QJsonDocument 类
    Lambda表达式特点
    【免费送书】机器学习和数据分析的关系是怎么样的,要学习的话哪者为先?
  • 原文地址:https://blog.csdn.net/m0_67403073/article/details/126515475
    • 最新文章
    • 攻防演习之三天拿下官网站群
      数据安全治理学习——前期安全规划和安全管理体系建设
      企业安全 | 企业内一次钓鱼演练准备过程
      内网渗透测试 | Kerberos协议及其部分攻击手法
      0day的产生 | 不懂代码的"代码审计"
      安装scrcpy-client模块av模块异常,环境问题解决方案
      leetcode hot100【LeetCode 279. 完全平方数】java实现
      OpenWrt下安装Mosquitto
      AnatoMask论文汇总
      【AI日记】24.11.01 LangChain、openai api和github copilot
    • 热门文章
    • 十款代码表白小特效 一个比一个浪漫 赶紧收藏起来吧!!!
      奉劝各位学弟学妹们,该打造你的技术影响力了!
      五年了,我在 CSDN 的两个一百万。
      Java俄罗斯方块,老程序员花了一个周末,连接中学年代!
      面试官都震惊,你这网络基础可以啊!
      你真的会用百度吗?我不信 — 那些不为人知的搜索引擎语法
      心情不好的时候,用 Python 画棵樱花树送给自己吧
      通宵一晚做出来的一款类似CS的第一人称射击游戏Demo!原来做游戏也不是很难,连憨憨学妹都学会了!
      13 万字 C 语言从入门到精通保姆级教程2021 年版
      10行代码集2000张美女图,Python爬虫120例,再上征途
    Copyright © 2022 侵权请联系2656653265@qq.com    京ICP备2022015340号-1
    正则表达式工具 cron表达式工具 密码生成工具

    京公网安备 11010502049817号