<>使用ThreadLocal替代Session完成保存用户登录信息功能

使用ThreadLocal替代Session的好处:

* 可以在同一线程中很方便的获取用户信息,不需要频繁的传递session对象。
具体实现流程:

* 在登录业务代码中,当用户登录成功时,生成一个登录凭证存储到redis中,将凭证中的字符串保存在cookie中返回给客户端。
*
使用一个拦截器拦截请求,从cookie中获取凭证字符串与redis中的凭证进行匹配,获取用户信息,将用户信息存储到ThreadLocal中,在本次请求中持有用户信息,即可在后续操作中使用到用户信息。
登录凭证类:
//登录凭证表 @Data @ApiModel("登录凭证类") public class LoginTicket { private int id;
private int userId; //登录凭证字符串 private String ticket; private int status; private
Date expired; }
ThreadLocal类:

*
ThreadLocal本质是以线程为key存储元素

*
ThreadLocal可以把用户信息保存在线程中,用户的每一次请求,就是一个线程,保存了用户信息,方便我们在后续操作获取用户登录信息。

*
当请求结束,我们会把保存的用户信息清除掉,防止内存泄漏。
/** *持有用户信息,用于代替session对象 */ @Component public class HostHolder {
//ThreadLocal本质是以线程为key存储元素 private ThreadLocal<User> users = new ThreadLocal<>(
); public void setUser(User user){ users.set(user); } public User getUser(){
return users.get(); } public void clear(){ users.remove(); } }
拦截器:

*
拦截每一次请求,从cookie中获取凭证字符串与redis中的凭证进行匹配,获取用户信息,将用户信息存储到ThreadLocal中,在本次请求中持有用户信息,即可在后续操作中使用到用户信息
@Component public class LoginTicketInterceptor implements HandlerInterceptor {
@Autowired private UserService userService; @Autowired private HostHolder
hostHolder; // 保存登录信息 // 调用时间:Controller方法处理之前 @Override public boolean
preHandle(HttpServletRequest request, HttpServletResponse response, Object
handler) throws Exception { //从cookie中获取凭证 String ticket = CookieUtil.getValue(
request, "ticket"); if (ticket != null){ //查询凭证 LoginTicket loginTicket =
userService.findLoginTicket(ticket); //检查凭证是否有效 if (loginTicket != null &&
loginTicket.getStatus() == 0 && loginTicket.getExpired().after(new Date())){
//根据凭证查询用户 User user = userService.findByUserId(loginTicket.getUserId());
//在本次请求中持有用户 hostHolder.setUser(user);
//构建用户认证的结果,并存入SecurityContext,以便于Security进行授权 Authentication authentication =
new UsernamePasswordAuthenticationToken( user, user.getPassword(), userService.
getAuthorities(user.getId())); SecurityContextHolder.setContext(new
SecurityContextImpl(authentication)); } } return true; } //
调用时间:Controller方法处理完之后 @Override public void postHandle(HttpServletRequest
request, HttpServletResponse response, Object handler, ModelAndView modelAndView
) throws Exception { //得到当前线程持有的user User user = hostHolder.getUser(); if (user
!= null && modelAndView != null){ modelAndView.addObject("loginUser", user); } }
// 调用时间:DispatcherServlet进行视图的渲染之后 // 请求结束,把保存的用户信息清除掉 @Override public void
afterCompletion(HttpServletRequest request, HttpServletResponse response,
Object handler, Exception ex) throws Exception { hostHolder.clear();
SecurityContextHolder.clearContext(); } }

技术
今日推荐
阅读数 6783
阅读数 1922
阅读数 1504
阅读数 1291
阅读数 1254
阅读数 1134
下载桌面版
GitHub
百度网盘(提取码:draw)
Gitee
云服务器优惠
阿里云优惠券
腾讯云优惠券
华为云优惠券
站点信息
问题反馈
邮箱:ixiaoyang8@qq.com
QQ群:766591547
关注微信