使用ThreadLocal好处
ThreadLocal可以将用户信息保存在线程中,当请求结束后我们在把保存的信息清除掉。这样我们才开发的时候就可以直接从全局的ThreadLocal中很方便的获取用户信息。
使用ThreadLocal,可以在同一线程中很方便的获取用户信息,不需要频繁的传递session对象。
ThreadLocal实现流程
- 首先创建ThreadLocal类,在其中设置相关的添加、获取以及删除方法。
- 创建登录拦截器,重写其中的
preHandle()
和afterCompletion()
方法。 - 注册拦截器
在日常开发中我们可以根据自己需要去获取用户信息,比如从token解析等
ThreadLocal实现流程
- 首先创建ThreadLocal类,在其中设置相关的添加、获取以及删除方法。
- 创建登录拦截器,重写其中的
preHandle()
和afterCompletion()
方法。 - 注册拦截器
在日常开发中我们可以根据自己需要去获取用户信息,比如从token解析等
代码实现:
ThreadLocal类:
packagecom.huing.blog.utils; importcom.huing.blog.dao.pojo.SysUser; /*** @author huing* @create 2022-06-24 14:01*/publicclassUserThreadLocal { privateUserThreadLocal(){} privatestaticfinalThreadLocal<SysUser>LOCAL=newThreadLocal<>(); publicstaticvoidput(SysUsersysUser){ LOCAL.set(sysUser); } publicstaticSysUserget(){ returnLOCAL.get(); } publicstaticvoidremove(){ LOCAL.remove(); } }
拦截器:
在preHandle()
方法中根据自己的需要将用户的登录信息存放之ThreadLocal中即可。
然后最后记得清除相关数据以避免内存泄漏
packagecom.huing.blog.handler; importcom.alibaba.fastjson.JSON; importcom.huing.blog.dao.pojo.SysUser; importcom.huing.blog.service.LoginService; importcom.huing.blog.utils.UserThreadLocal; importcom.huing.blog.vo.ErrorCode; importcom.huing.blog.vo.Result; importlombok.extern.slf4j.Slf4j; importorg.apache.commons.lang3.StringUtils; importorg.springframework.beans.factory.annotation.Autowired; importorg.springframework.stereotype.Component; importorg.springframework.web.method.HandlerMethod; importorg.springframework.web.servlet.HandlerInterceptor; importjavax.servlet.http.HttpServletRequest; importjavax.servlet.http.HttpServletResponse; /*** @author huing* @create 2022-06-24 13:14*/publicclassLoginInterceptorimplementsHandlerInterceptor { privateLoginServiceloginService; publicbooleanpreHandle(HttpServletRequestrequest, HttpServletResponseresponse, Objecthandler) throwsException { //登录验证成功,放行//我希望在controller中直接获取用户的信息怎么获取UserThreadLocal.put(sysUser); returntrue; } publicvoidafterCompletion(HttpServletRequestrequest, HttpServletResponseresponse, Objecthandler, Exceptionex) throwsException { //如果不删 ThreadLocal中用完的信息会有内存泄漏的风险UserThreadLocal.remove(); } }
注册自定义拦截器:
packagecom.huing.blog.config; importcom.huing.blog.handler.LoginInterceptor; importorg.springframework.beans.factory.annotation.Autowired; importorg.springframework.context.annotation.Configuration; importorg.springframework.web.servlet.config.annotation.CorsRegistry; importorg.springframework.web.servlet.config.annotation.InterceptorRegistry; importorg.springframework.web.servlet.config.annotation.WebMvcConfigurer; /*** @author huing* @create 2022-06-11 18:45*/publicclassWebMVCConfigimplementsWebMvcConfigurer { privateLoginInterceptorloginInterceptor; publicvoidaddInterceptors(InterceptorRegistryregistry) { //假设拦截test接口 后续实际遇到拦截的接口是时,再配置真正的拦截接口// registry.addInterceptor(loginInterceptor).addPathPatterns("/**").excludePathPatterns("/login").excludePathPatterns("/register"); //拦截所有,排除登录注册接口registry.addInterceptor(loginInterceptor) .addPathPatterns("/test") .addPathPatterns("/comments/create/change") .addPathPatterns("/articles/publish"); } }
自行编写接口测试,直接通过ThreadLocal返回用户的登录信息
packagecom.huing.blog.controller; importcom.huing.blog.dao.pojo.SysUser; importcom.huing.blog.utils.UserThreadLocal; importcom.huing.blog.vo.Result; importorg.springframework.web.bind.annotation.RequestMapping; importorg.springframework.web.bind.annotation.RestController; /*** @author huing* @create 2022-06-24 13:34*/"test") (publicclassTestController { publicResulttest(){ SysUsersysUser=UserThreadLocal.get(); System.out.println(sysUser); returnResult.success(null); } }