日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

采用redis+ThreadLocal获取全局的登录用户信息(一)

發布時間:2023/12/31 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 采用redis+ThreadLocal获取全局的登录用户信息(一) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1.首先進行登錄操作,代碼已經假設你從數據庫拿到了用戶信息保存在變量userinfo中,將token返回給瀏覽器保存,并將token和userinfo保存在redis中。

@Resourceprivate RedisTemplate redisTemplate;@RequestMapping("/login")public R token(HttpServletRequest request, HttpServletResponse response) {//假設此時已經從數據庫獲取到用戶信息在userinfoString token = UUID.randomUUID().toString();Cookie cookie=new Cookie("tokenUser",token);cookie.setMaxAge(60 * 60 * 24 * 7);//有效期設為7天cookie.setPath("/");//設置路徑response.addCookie(cookie);//響應回游覽器RedisCache redis=new RedisCache(redisTemplate);redis.set(token,userinfo,60 * 60 * 24 * 7);//有效期設為7天return R.ok(userinfo,"登錄成功");}

2.新建一個類型,這個是全局線程。當用戶信息經過token驗證從redis拿出來之后要保存在這個里面,想用的時候從這個里面拿取就行了。

public class UserThreadLocal {private static ThreadLocal<User> userThread =new ThreadLocal<User>();public static void set(User user){userThread.set(user);}public static User get(){return userThread.get();}//防止內存泄漏public static void remove(){userThread.remove();} }

3.新建一個攔截器,業務邏輯是 獲取瀏覽器token,再從redis獲取userinfo,將userinfo保存在UserThreadLocal線程中。

@Configuration public class LoginInterceptor implements HandlerInterceptor {@Resourceprivate RedisTemplate redisTemplate;@Autowiredprivate static ObjectMapper objectMapper = new ObjectMapper();//在執行COntroller方法之前執行/*** boolean 表示是否放行* true:放行 用戶可以跳轉頁面* false:攔截 之后給定重定向路徑** 業務邏輯:* 1.判斷用戶客戶端是否有Cookie/token數據* 如果用戶沒有token則重定向到用戶登陸頁面* 2.如果用戶token中有數據,則從redis緩存中獲取數據* 如果redis中數據為null,則重定向到用戶登陸頁面* 3.如果reids中有數據,則放行請求.*/@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)throws Exception {String token = "";//獲取Cookie數據Cookie[] cookies = request.getCookies();for (Cookie cookie : cookies) {if("tokenUser".equals(cookie.getName())){token = cookie.getValue();break;}}//判斷Cookie是否為nullif(!StringUtils.isEmpty(token)){System.out.println(token);//檢測緩存中是否有該數據RedisCache redis=new RedisCache(redisTemplate);Object userinfo= redis.get(token);System.out.println(userinfo);if(!StringUtils.isEmpty(userinfo)){//將userJSON轉化為User對象User user= (User) userinfo;UserThreadLocal.set(user);//用戶已經登陸 放行請求return true;}}//表示用戶沒有登陸response.sendRedirect("/login.html");return false;}//執行完業務邏輯后攔截@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,ModelAndView modelAndView) throws Exception {// TODO Auto-generated method stub}//返回頁面之前攔截@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)throws Exception {//將ThreadLocal數據清空UserThreadLocal.remove();}}

3.新建一個攔截器配置類,設置要訪問攔截器的路徑,開放登錄接口和靜態資源接口,其他都配置成要訪問攔截器

@Configuration public class InterceptorConfig implements WebMvcConfigurer {@Autowiredprivate LoginInterceptor loginInterceptor;@Overridepublic void addInterceptors(InterceptorRegistry registry){//添加對用戶未登錄的攔截器,并添加排除項registry.addInterceptor(loginInterceptor).addPathPatterns("/**")//攔截所有.excludePathPatterns("/js/**","/dist/images/**")//排除樣式、腳本、圖片等資源文件.excludePathPatterns("/login")//排除登錄.excludePathPatterns("/","/index");} }

4.獲取用戶信息。

@RequestMapping("/getuserinfo")public R getuserinfo() {User user = UserThreadLocal.get();System.out.println(user);return R.ok(user,"獲取用戶信息成功");}

?問:ThreadLocal如何確保每次都能取到對應的信息?

?答:每次執行請求時攔截器將用戶信息保存在ThreadLocal中,ThreadLocal每次調用set時是一個獨立的線程,當另一個用戶調用ThreadLocal的set時方法?時,就會新建另一個線程,線程之間互不影響,當對應線程在調用get時候,就會請求到set時候的信息。

?問:怎么保證線程過多內存不會溢出呢?

?答:在攔截器的afterCompletion方法中添加ThreadLocal線程刪除方法,這樣每次請求結束后會將ThreadLocal線程中的數據刪除,這樣保證了線程不會太多,內存不會溢出。

總結

以上是生活随笔為你收集整理的采用redis+ThreadLocal获取全局的登录用户信息(一)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。