ThreadLocal存用户信息?

3 篇文章 0 订阅
3 篇文章 0 订阅
本文介绍了如何利用Spring的RequestContextHolder和ServletRequestAttributes避免手动管理ThreadLocal来存储和获取用户信息。通过封装工具类,可以在过滤器、拦截器、AOP等场景便捷地操作用户ID,同时指出ServletRequestAttributes对象已经在ThreadLocal中,无需额外处理生命周期。
摘要由CSDN通过智能技术生成

最近看很多视频讲ThreadLocal存用户信息,是的没问题但有点多余,因为有现成的

上代码

封装工具类即可在过滤器、拦截器、aop等地方使用(转发重定向动手试试吧印象更深刻,子线程或线程池需要使用阿里的threadLoacl

import java.util.Optional;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import lombok.extern.slf4j.Slf4j;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;


@Slf4j
public class WebUtil {

    private static final String USERID_ATTRIBUTE_NAME = "_user_id";


    public static void setUserId(Integer userId) {
        setAttribute(USERID_ATTRIBUTE_NAME, userId);
    }


    public static Integer getUserId() {
        return Optional.ofNullable((Integer) getAttribute(USERID_ATTRIBUTE_NAME)).orElse(null);
    }

    /**
     * 取
     */
    public static Object getAttribute(String name) {
        return getRequest().getAttribute(name);
    }

    /**
     * 存
     */
    public static void setAttribute(String name, Object val) {
        getRequest().setAttribute(name, val);
    }

    /**
     * 获取 HttpServletRequest
     */
    public static HttpServletRequest getRequest() {
        return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
                .getRequest();
    }

    /**
     * 获取 HttpServletResponse
     */
    public static HttpServletResponse getResponse() {
        return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
                .getResponse();
    }


}

源码

可以看到ServletRequestAttributes对象就在ThreadLocal中,无需自己处理生命周期
而HttpServletRequest可已从ServletRequestAttributes中获取

public abstract class RequestContextHolder {
	private static final ThreadLocal<RequestAttributes> requestAttributesHolder = new NamedThreadLocal("Request attributes");
    private static final ThreadLocal<RequestAttributes> inheritableRequestAttributesHolder = new NamedInheritableThreadLocal("Request context");
    
	public static void resetRequestAttributes() {
        requestAttributesHolder.remove();
        inheritableRequestAttributesHolder.remove();
    }
    
	@Nullable
    public static RequestAttributes getRequestAttributes() {
        RequestAttributes attributes = (RequestAttributes)requestAttributesHolder.get();
        if (attributes == null) {
            attributes = (RequestAttributes)inheritableRequestAttributesHolder.get();
        }

        return attributes;
    }
}

而我们的需要的东西就保存在这里了,一个ConcurrentHashMap

public class Request implements HttpServletRequest {
	private final Map<String, Object> attributes = new ConcurrentHashMap<>();
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ThreadLocal泄露问题是指当使用ThreadLocal类时,如果没有正确地进行清理和处理,就有可能导致内泄露的情况发生。这是因为ThreadLocal对象的生命周期与线程的生命周期相对独立,当线程结束时,ThreadLocal对象没有被垃圾回收,且其中储的数据也无法被访问,从而导致内泄露。 具体来说,ThreadLocal类通过操作ThreadLocalMap来储每个线程的数据。当一个线程结束时,如果没有正确地清理ThreadLocal对象,那么ThreadLocalMap中与该线程相关的条目将无法被删除。这意味着,即使这些条目对应的线程不再活跃,它们却仍然占据着内空间。 一种常见的导致ThreadLocal泄露的情况是在使用完ThreadLocal对象后未调用其remove方法进行清理操作。如果在一个长时间运行的线程中重复使用ThreadLocal对象,而不进行清理操作,就会导致ThreadLocalMap中的条目越来越多,从而造成内泄露。 另外,当ThreadLocal对象被作为静态变量使用时,也容易出现内泄露的问题。因为静态变量的生命周期很长,如果静态ThreadLocal对象没有被妥善处理,那么其中的数据也将无法被释放。 为了避免ThreadLocal泄露,应该养成良好的编程习惯,确保在使用完ThreadLocal对象后,及时调用其remove方法进行清理。另外,如果ThreadLocal对象被用作静态变量,也应该在不再使用时手动将其置为null,以便让垃圾回收器能够回收相关的内空间。 参考资料: :可以发现问题,ThreadLocal已经被清理掉了,代表现在已经没有方式去访问当前ThreadLocal到Map里的value数据了 。 :ThreadLocal就相当于一个访问工具类,通过操作ThreadLocal对象的方法 来操作储在当前线程内部的ThreadLocalMap里的值 。 :一篇文章我们来分析一个JavaThreadLocal泄露的案例。分析问题的过程比结果更重要,理论结合实际才能彻底分析出内泄漏的原因。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值