1.首先进行登录操作,代码已经假设你从数据库拿到了用户信息保存在变量userinfo中,将token返回给浏览器保存,并将token和userinfo保存在redis中。
@Resource
private RedisTemplate redisTemplate;
@RequestMapping("/login")
public R token(HttpServletRequest request, HttpServletResponse response) {
//假设此时已经从数据库获取到用户信息在userinfo
String 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 {
@Resource
private RedisTemplate redisTemplate;
@Autowired
private static ObjectMapper objectMapper = new ObjectMapper();
//在执行COntroller方法之前执行
/**
* boolean 表示是否放行
* true:放行 用户可以跳转页面
* false:拦截 之后给定重定向路径
*
* 业务逻辑:
* 1.判断用户客户端是否有Cookie/token数据
* 如果用户没有token则重定向到用户登陆页面
* 2.如果用户token中有数据,则从redis缓存中获取数据
* 如果redis中数据为null,则重定向到用户登陆页面
* 3.如果reids中有数据,则放行请求.
*/
@Override
public 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是否为null
if(!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;
}
//执行完业务逻辑后拦截
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
// TODO Auto-generated method stub
}
//返回页面之前拦截
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
//将ThreadLocal数据清空
UserThreadLocal.remove();
}
}
3.新建一个拦截器配置类,设置要访问拦截器的路径,开放登录接口和静态资源接口,其他都配置成要访问拦截器
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
@Autowired
private LoginInterceptor loginInterceptor;
@Override
public 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,"获取用户信息成功");
}