ThreadLocal使用场景

本文描述了作者在项目中如何使用ThreadLocal存储用户工号和语言代码,作为拦截器处理请求头信息,同时强调了ThreadLocal的线程隔离性和内存管理的重要性。
摘要由CSDN通过智能技术生成
对于ThreadLocal的使用场景,网上的我感觉都比较不那么贴切。我就写一个目前自己项目里真实用到的场景。
我的需求场景是:用户在查询/写入数据的时候,我要拿到他的工号以及展示语言而去做对应的操作。我设想的是有那么一处地方可以拿到信息暂时存下来,后续的任何操作get一下即可,废话不多说,先上代码。
 
1.拦截器
/**
 * @Author: zzzz
 * @Date: 2024/01/28/15:46
 * @Description: header信息拦截器
 */
public class HeaderInterceptor implements HandlerInterceptor {

    public static final String USER_NO_HEADER = "iv_user";

    public static final String LANGUAGE_CODE = "langCode";

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handle) {

        HeaderInfo headerInfo = new HeaderInfo();

        //获取请求头信息
        String operatorId = request.getHeader(USER_NO_HEADER);
        String language = request.getHeader(LANGUAGE_CODE);

        if (StringUtils.isNotBlank(operatorId)) {
            headerInfo.setOperatorId(operatorId);
        }

        if (StringUtils.isNotBlank(language)) {
            headerInfo.setLanguage(language);
        }

        //封装数据
        HeaderContext.getHeaderContext().setHeaderInfo(headerInfo);

        return true;
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception e) {

        HeaderContext.getHeaderContext().remove();
    }
2.ThreadLocal
/**
 * @Author: zzzz
 * @Date: 2024/01/28/16:02
 * @Description: header头信息上下文
 */
public class HeaderContext {

    private static ThreadLocal<HeaderInfo> header = new ThreadLocal<>();

    public HeaderContext() {
    }

    public static HeaderContext getHeaderContext() {
        HeaderContext context = new HeaderContext();
        return context;
    }

    public void setHeaderInfo(HeaderInfo headerInfo) {
        header.set(headerInfo);
    }

    public String getOperationId() {
        return header.get() == null ? "" : header.get().getOperatorId();
    }

    public String getLanguage() {
        return header.get() == null ? "" : header.get().getLanguage();
    }

    public void remove() {
        header.remove();
    }
3.实体
/**
 * @Author: zzzz
 * @Date: 2024/01/28/15:51
 * @Description: 请求头信息
 */
@Data
public class HeaderInfo {

    /**
     * 用户
     */
    private String operatorId;

    /**
     * 语言
     */
    private String language;
}
4.bean注入
    @Bean
    public HandlerInterceptor setBean() {
        return new HeaderInterceptor();
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(setBean());
    }
5.调用
        String operationId = HeaderContext.getHeaderContext().getOperationId();
总结一下:
ThreadLocal叫做线程变量,意思是ThreadLocal中填充的变量属于当前线程,该变量对其他线程而言是隔离的,也就是说该变量是当前线程独有的变量。ThreadLocal为变量在每个线程中都创建了一个副本,那么每个线程可以访问自己内部的副本变量。
基于这个特性我把它用到了这里,最后提醒一下:

基于源码可以看出它是基于自身为key,传入的值作为value的键值对形式,因为key的弱引用在gc之后会变成(null,value)的形式,之后便无法回收,就会导致内存上的风险。
 

在使用完之后,必须要注意调用一下remove;
 

有错误的地方欢迎大家指出!!!来自一位菜鸟开发。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值