登录拦截器
作者:互联网
步骤:
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