其他分享
首页 > 其他分享> > 登录拦截器

登录拦截器

作者:互联网

步骤: 

     1、解密jwt

     2、传递登录用户信息,

               可与通过   // request.setAttribute("loginUser",loginUser); 来传递用户信息

              也可通过threadlocal来传递。

threadlocal  同一个线程共享的变量,方便同一个线程的其他方法获取该信息。避免了传参,相当于同一个线程的全局变量。

使用场景:用户登录令牌解密后的信息传递,还有用户权限信息,从用户系统获取到的用户名

用户id等信息。

 public static ThreadLocal<LoginUser> threadLocal = new ThreadLocal<>();
 threadLocal.set(loginUser);
 threadLocal.get();
 threadLocal.remove();
 // 源码
 public void set(T value) {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null)
            map.set(this, value);
        else
            createMap(t, value);
    }

static class ThreadLocalMap {

        /**
         * The entries in this hash map extend WeakReference, using
         * its main ref field as the key (which is always a
         * ThreadLocal object).  Note that null keys (i.e. entry.get()
         * == null) mean that the key is no longer referenced, so the
         * entry can be expunged from table.  Such entries are referred to
         * as "stale entries" in the code that follows.
         */
        static class Entry extends WeakReference<ThreadLocal<?>> {
            /** The value associated with this ThreadLocal. */
            Object value;

            Entry(ThreadLocal<?> k, Object v) {
                super(k);
                value = v;
            }
        }

threadlocal --- 底层是threadlocalmap ---- 弱引用  WeakReference<ThreadLocal<?>>

关于threadlocal的常见题目

1、threadlocal和sychronized的区别

      都是为了解决并发冲突问题

      synchronized 是通过线程等待,牺牲时间来解决访问冲突;threadlocal是通过每个线程单独一份存储空间,牺牲空间来解决冲突问题。

     对比sychronized,threadlocal具有线程隔离的效果,只有在线程内才能获取对应的值,线程外则不能访问到想要的值。

2、为啥threadlocal是弱引用weakreference,如果是强引用会怎样?

java中除了基础的数据类型,其他都是引用类型;

如果是强引用,即使把threadlocal设置为null,但是threadlocalmap还持有threadlocal的强引用,如果没有手动删除,threadlocal不会被回收,导致entry内存泄露。

如果是弱引用:

引用threadlocal的对象被回收,由于threadlocalmap持有threadlocal的弱引用,即使没有手动删除,threadlocal也会被回收,value在下一次threadlocalmap调用set get remove 的时候就会被清除

/**
 * 存放拦截器的包
 * 拦截器需要继承 HandlerInterceptor
 */

@Slf4j
public class LoginInterceptor implements HandlerInterceptor {

    /**
     * 存储token
     */
    public static ThreadLocal<LoginUser> threadLocal = new ThreadLocal<>();

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 获取token
        String accessToken = request.getHeader("token");
        // 有些情况下head不能通过head进行传递,而是通过url进行传递
        if(accessToken == null){
           accessToken =  request.getParameter("token");
        }


        if(StringUtils.isNotBlank(accessToken)){
            // 不为空
            Claims claims = JWTUtil.checkJWT(accessToken);
            if(claims== null){
                // 未登录
                CommonUtil.sendJsonMessage(response, JsonData.buildResult(BizCodeEnum.ACCOUNT_UNLOGIN));
                return false;
            }

            // 已经登录的时候
           long userId =  Long.valueOf(claims.get("id").toString());
            String headImg = (String)claims.get("head_img");
            String name = (String)claims.get("name");
            String mail = (String)claims.get("mail");

            LoginUser loginUser = new LoginUser();
            loginUser.setHeadImg(headImg);
            loginUser.setId(userId);
            loginUser.setMail(mail);
            loginUser.setName(name);

            /**
             * 解密后需要传递登录信息
             */
            // 通过attribute传递用户信息
           // request.setAttribute("loginUser",loginUser);
            // 通过threadlocal传递用户信息 TODO
            threadLocal.set(loginUser);


            return true;
        }
        CommonUtil.sendJsonMessage(response,JsonData.buildResult(BizCodeEnum.ACCOUNT_UNLOGIN));
        return false;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
    }
}

 

标签:拦截器,登录,get,request,ThreadLocal,threadlocal,线程,loginUser
来源: https://blog.csdn.net/weixin_45063957/article/details/120357808