threadlocal用法及原理

本文介绍了一个JavaWeb应用中如何使用ThreadLocal实现跨请求的会话管理。通过UserSessionFilter过滤器,文章详细展示了如何在HTTP会话(HttpSession)与线程局部变量(ThreadLocal)之间传递用户会话数据。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

用一个简单的java web实例来说明:

UserSessionFilter.java 过滤器

HttpSession httpsession = ((HttpServletRequest)req).getSession();

private static ThreadLocal<HttpSession> session = new ThreadLocal<HttpSession>();

UserSessionFilter.session.set(httpsession); >>>  本类中的session初始值为HttpSession


Object userSession = httpsession.getAttribute("user");  >>> 从HttpSession中取得"user"的值

ThreadLocalUserSession.set(userSession);   >>> 将从HttpSession中取得"user"的值设置到ThreadLocal中


Map<String, Object> map = (Map<String, Object>)session.getAttribute("vars");  取HttpSession中的"vars"并设置到ThreadLocalUserSession类中
ThreadLocalUserSession.setVars(map);


UserSessionUtil.java 工具类

设置session:

1.

UserSessionFilter.getHttpSession().setAttribute("user", userSession); >>> 本质是往HttpSession中设置

ThreadLocalUserSession.set(userSession);  >>> 本质是往ThreadLocal中设置

2.

UserSessionFilter.getHttpSession().setAttribute("vars", vars); >>> 本质是往HttpSession中设置
ThreadLocalUserSession.setVars(vars);  >>> 本质是往ThreadLocal中设置


取值session:

ThreadLocal.get(); >>> 本质是从ThreadLocal中取值


====================================

web.xml:

<filter>
       <filter-name>UserSessionFilter</filter-name>
       <filter-class>com.licaike.framework.server.filter.UserSessionFilter</filter-class>
</filter>
<filter-mapping>
      <filter-name>UserSessionFilter</filter-name>
      <url-pattern>/*</url-pattern>
</filter-mapping>


UserSessionFilter.java:

public class UserSessionFilter implements Filter{
    private static ThreadLocal<HttpSession> session = new ThreadLocal<HttpSession>();
    
    public void destroy() {
    }
    
    public static HttpSession getHttpSession(){
        return UserSessionFilter.session.get();
    }
    
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain filterChain) throws IOException, ServletException {
        // 仅仅是记录下WEB session
        HttpSession session = ((HttpServletRequest)req).getSession();
        UserSessionFilter.session.set(session);
      

        //设置用户身份信息
        Object userSession = session.getAttribute("user");
        ThreadLocalUserSession.set(userSession);

        // 设置session变量
        Map<String, Object> map = (Map<String, Object>)session.getAttribute("vars");
        if(map == null){
            map = new HashMap<String,Object>();
        }
        ThreadLocalUserSession.setVars(map);
        filterChain.doFilter(req, res);
    }

    public void init(FilterConfig arg0) throws ServletException {
    }

}


UserSessionUtil.java:

public class UserSessionUtil {
    public static UserSession get(){
        return (UserSession)ThreadLocalUserSession.get();
    }
    
    //调用此方法真正写入到session
    public static void set(UserSession userSession){
        UserSessionFilter.getHttpSession().setAttribute("user", userSession);  //过滤器里设到本地线程变量里
        ThreadLocalUserSession.set(userSession);  //此处设到本地线程变量里
    }
    
    public static Map<String,Object> getVars(){
        return ThreadLocalUserSession.getVars();
    }
    
    public static void setVars(Map<String,Object> vars){
        UserSessionFilter.getHttpSession().setAttribute("vars", vars);  //过滤器里设到本地线程变量里
        ThreadLocalUserSession.setVars(vars); //此处设到本地线程变量里
    }
    
    public static void initSession(){
        //初始化userSession
        if(get()==null) set(new UserSession());
        //初始化其他
        if(getVars()==null) setVars(new HashMap<String,Object>());
    }
}


ThreadLocalUserSession.java:

public class ThreadLocalUserSession implements Serializable{
    private static ThreadLocal<Object> threadLocalUserSession = new ThreadLocal<Object>() ;
    private static ThreadLocal<Map<String,Object>> vars = new ThreadLocal<Map<String,Object>>() ;
    
    public static void set(Object object){
        threadLocalUserSession.set(object);
    }
    public static Object get(){
        Object object = threadLocalUserSession.get();
        return object;
    }

    public static void setVars(Map<String,Object> vars){
        ThreadLocalUserSession.vars.set(vars);
    }
    public static Map<String,Object> getVars(){
        Map<String,Object> map = vars.get();
        return map;
    }

    private static final long serialVersionUID = 4343534534354L;
}


====================================

关于Theadlocal的说明:

进入Theadlocal代码,可以发现如下的片段:

public T get() {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null) {
            ThreadLocalMap.Entry e = map.getEntry(this);
            if (e != null)
                return (T)e.value;
        }
        return setInitialValue();
    }

这说明ThreadLocal确实只有一个变量,但是它内部包含一个map,针对每个thread保留一个entry。









评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值