博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
自用日志中ThreadLocal的使用
阅读量:6241 次
发布时间:2019-06-22

本文共 2132 字,大约阅读时间需要 7 分钟。

title: 自用日志中ThreadLocal的使用 date: 2017.04.15 23:07 categories:

  • 技术博客 tags:
  • 实现方式
  • 日志

接到一个技术类需求,碰到了几个比较有意思的点。

主需求:实现自用的日志记录

基本思路:新增一张systemlog表用于存放数据,利用AOP的思想截获用户的操作行为,增强类中处理具体的操作数据,存入log表,实现分下面两步。

1. 配置增强类AOP

  • bean的配置
  • AOP的配置(切点,增强 | 通知,切面)

2. 增强类实现

  • 该类的作用定位为工具,因此命名为LogUtil,放入util包中(遵循规范)。
  • 业务代码

重点是ThreadLocal相关

这次的需求让我回想到了之前关于session的几个点,原因是思路有些重合,看回这个需求,日志的记录要求用户的每次交互都作为数据存入log表,其中表字段设计时需要存入用户对象信息,一见这样的模式就要想到session,可是session无法直接获取,因而需要一个中间层来处理他,这一次就用到了ThreadLocal。

设想一下:用户进入web,每次操作都通过一个触发点将单次请求存起来,每一次的获取我使用拦截器来实现(以后再聊),而放请求这个动作就需要了解Thread的两个小伙伴。

ThreadLocal是与线程绑定的,可以完成这样的需求(log表中记录登录用户)。 核心类:

  • Thread:表示线程对象
  • ThreadLocal:线程通过该类拷贝进行存值的操作
  • ThreadLocalMap:线程自带的容器类,类似Map但有区别,当下没必要纠结其细节

看看JDK1.8源码:

  • ThreadLocal中的get
    public T get() {        Thread t = Thread.currentThread();        ThreadLocalMap map = getMap(t);        if (map != null) {            ThreadLocalMap.Entry e = map.getEntry(this);            if (e != null) {                @SuppressWarnings("unchecked")                T result = (T)e.value;                return result;            }        }        return setInitialValue();    }复制代码

原英文注释写的很清楚了:该方法返回当前线程中local变量的副本。

  • ThreadLocal中的set
    public void set(T value) {        Thread t = Thread.currentThread();        ThreadLocalMap map = getMap(t);        if (map != null)            map.set(this, value);        else            createMap(t, value);    }复制代码

作用:将传入的value放入线程中的map。

  • ThreadLocalMap中的set
 private void set(ThreadLocal
key, Object value) {...}复制代码

作用:将调用该方法的local变量作为key,传入的值作为value放入自定义的map结构中。

关于ThreadLocal的分析网上有很多,今天我不聊过多,说一个思路吧:看源码的时候要学会简化,比如尽可能去抓源码中关键的地方,必要时候配合画类图+脑图的方式,我把类结构简单拿了一下:

因此到这里,我可以试着实现前面的思路,在SharedContext共用类中添加ThreadLocal成员与静态方法,用于完成对request的存取:

public static ThreadLocal
local=new ThreadLocal();//本地线程变量public static void setReq(HttpServletRequest req){ local.set(req);//将请求存到那个map中}public static HttpServletRequest getReq(){ return local.get();//拿出来}复制代码

到了LogUtil中业务代码(记录日志功能),我们就可以通过SharedContext共用类获取到当前请求对象(本次是获取session然后拿到user数据),而在取之前要根据自家业务需求在对应的地方存入请求,SharedContext是共用静态的,所以伸缩性很强。

到这里,这个需求的重点之一已经完成了。

小结

  • 思路要清晰
  • 设计好了就去尝试
  • 出问题有很多解决方案(前人的经验)
  • 看源码也有技巧(光能读英语还不够)

转载地址:http://mmcia.baihongyu.com/

你可能感兴趣的文章
使用ffmpeg将录屏文件转换成gif
查看>>
作业七 总结
查看>>
Oracle的静默安装 升级和卸载 参考规范
查看>>
高效存储过程分页
查看>>
电脑用U盘启动
查看>>
Web漏洞扫描
查看>>
使用xtrabackup做数据库的增量备份
查看>>
“程序已停止工作”问题的解决方法,停止解决方法
查看>>
[c++] 幂法求特征向量
查看>>
WEB项目(B/S系统)打包安装(总结篇)
查看>>
Cartographer源码阅读(8):imu_tracker
查看>>
U盘,移动硬盘显示显示需要格式化怎么修复
查看>>
JVM基础和调优(一)
查看>>
ICommand in Silverlight
查看>>
复选框、单选按钮、下拉列表的定义
查看>>
webdynpro的select_option示例
查看>>
img src 使用 base64 图片数据
查看>>
MapReduce计算每年最高温度
查看>>
Ruby快速入门
查看>>
UVA 12118 Inspector's Dilemma(连通性,欧拉路径,构造)
查看>>