springboot使用ThreadLocal登录保存用户信息

写一个拦截器,对请求方法进行拦截,拦截器会从请求的 header 中取 token 信息,如果 token 信息不存在,则证明用户尚未登录,让用户去登录。

如果 token 存在则去 redis 中查找用户的相关信息,我习惯只讲用户的 userCode 和名称这些简单的信息存储在 redis 里。redis 中查不到 userInfo 证明 token 不合法或者 token 是一个游客的 token,同样跳转登录注册界面。如果 userInfo 存在,则讲 userInfo 存储在 ThreadLocal 中,以便其他方法直接获取。

ThreadUtils

  1. package com.rumenz.token;
  2. import com.rumenz.token.UserInfo;
  3. public class ThreadUtils<T> {
  4. private static final ThreadLocal<String> tokenHolder = new ThreadLocal<>();
  5. private static final ThreadLocal<UserInfo> userHolder = new ThreadLocal<>();
  6. public static void setToken(String token){
  7. tokenHolder.set(token);
  8. }
  9. public static String getToken(){
  10. return tokenHolder.get();
  11. }
  12. public static void setUserHolder(UserInfo user){
  13. userHolder.set(user);
  14. }
  15. public static UserInfo getUserHolder(){
  16. return userHolder.get();
  17. }
  18. public static void remove(){
  19. tokenHolder.remove();
  20. userHolder.remove();
  21. }
  22. }

拦截器

  1. package com.rumenz.token;
  2. import org.springframework.context.annotation.Bean;
  3. import org.springframework.context.annotation.Configuration;
  4. import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
  5. import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
  6. @Configuration
  7. public class HealthWebConfigure extends WebMvcConfigurationSupport {
  8. @Bean
  9. public LoginInterceptor loginInterceptor(){
  10. return new LoginInterceptor();
  11. }
  12. @Override
  13. public void addInterceptors(InterceptorRegistry registry) {
  14. registry.addInterceptor(loginInterceptor())
  15. .addPathPatterns("/**")
  16. .excludePathPatterns("/thirdPartyLogin/sns")
  17. .excludePathPatterns("/login")
  18. .excludePathPatterns("/logout");
  19. super.addInterceptors(registry);
  20. }
  21. }
  1. package com.rumenz.token;
  2. import com.rumenz.token.utils.*;
  3. import com.rumenz.token.UserInfo;
  4. import org.apache.commons.lang.StringUtils;
  5. import org.springframework.beans.factory.annotation.Autowired;
  6. import org.springframework.web.servlet.HandlerInterceptor;
  7. import javax.servlet.http.HttpServletRequest;
  8. import javax.servlet.http.HttpServletResponse;
  9. public class LoginInterceptor implements HandlerInterceptor {
  10. @Autowired
  11. private RedisUtil redisUtil;
  12. @Override
  13. public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
  14. //token存在header中
  15. String token = request.getHeader("token");
  16. if(StringUtils.isBlank(token)){
  17. HttpRespUtil.respContent(response,R.error(PublicResultConstant.INVALID_PARAM_EMPTY.result,PublicResultConstant.INVALID_PARAM_EMPTY.msg));
  18. return false;
  19. }
  20. ThreadUtils.setToken(token);
  21. //根据token从redis获取用户信息是否存在登录
  22. UserInfo userInfo = (UserInfo) redisUtil.get(token);
  23. if(userInfo==null || StringUtils.isBlank(userInfo.getUserCode()) || userInfo.getId()==null){
  24. HttpRespUtil.respContent(response,R.error(PublicResultConstant.UNAUTHORIZED.result,PublicResultConstant.UNAUTHORIZED.msg));
  25. return false;
  26. }
  27. ThreadUtils.setUserHolder(userInfo);
  28. return true;
  29. }
  30. @Override
  31. public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
  32. ThreadUtils.remove();
  33. }
  34. }

Controller 层用户获取信息时的方法

  1. @RequestMapping("/list")
  2. public R list(){
  3. UserInfo userHolder = ThreadUtils.getUserHolder();
  4. if(userHolder!=null && StringUtils.isNotBlank(userHolder.getUserCode())){
  5. UserDataRecord record = new UserDataRecord();
  6. record.setUserCode(userHolder.getUserCode());
  7. List<UserDataRecord> list = userDataRecordService.findUserDataRecord(record);
  8. return R.ok().put("userDataRecordList",list);
  9. }
  10. return R.error(PublicResultConstant.PARAM_ERROR.result, PublicResultConstant.PARAM_ERROR.getMsg());
  11. }
返回笔记列表
入门小站