拦截器
在这里插入图片描述拦截器的作用在于将重复的登录校验功能安装在拦截器上(某些请求需要要求用户等登录才能启用)但不可能在每一个业务模块都写校验的代码,于是拦截器的作用就在于拦截请求 去检查用户的状态 是否处于在线 若是在线就刷新token的有效期 token存在Redis中
细节实现就不说了 实现部分的代码
这是一号拦截器 只需要检查ThreadLocal中是否有用户(有说明登录了,因为登录校验操作中会把用户信息存在ThreadLocal)
代码语言:text复制Java
public class LoginInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//1.判断是否需要拦截(ThreadLocal中是否有用户)
if (UserHolder.getUser() == null) {
response.setStatus(401);
return false;
}
return true;
}
}二号拦截器
这里我们注入了Redis因为要用Redis来存用户信息
代码语言:javascript复制public class RefreshTokeninterceptor implements HandlerInterceptor {
//而MvcConfig中使用了 LoginInterceptor 所以我们要去到MvcConfig进行注入
private StringRedisTemplate stringRedisTemplate;
//因为这个类不是spring boot构建的,而是手动创建的类,所以依赖注入不能用注解来注入,要我们手动使用构造函数来注入这个依赖
public RefreshTokeninterceptor(StringRedisTemplate stringRedisTemplate) {
this.stringRedisTemplate = stringRedisTemplate;
}
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//获取请求头中的token 在前端代码中详见authorization
String token = response.getHeader("authorization");
if(StrUtil.isBlankIfStr(token)){{//判断是否为空
return true;
}
// 基于token获取Redis用户
String Token = RedisConstants.LOGIN_USER_KEY token;
Map<Object,Object> UserMap = stringRedisTemplate.opsForHash().entries(Token);
//判断用户是否存在
if(UserMap.isEmpty()){
return true;
}
// 将查询到的hash数据转化为userDTO对象
//fillBeanWithMap是用UserMap来填充 UserDTO这个Bean,最后一个参数是你是否忽略转换过程中的错误
UserDTO user = BeanUtil.fillBeanWithMap(UserMap, new UserDTO(), false);
//存在 保存用户信息到TheadLocal
UserHolder.saveUser(user);
//刷新token有效期
stringRedisTemplate.expire(Token,RedisConstants.LOGIN_USER_TTL, TimeUnit.MINUTES);
//放行
response.setStatus(200);
return true;
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
//移除用户
UserHolder.removeUser();
}
}最后是配置拦截器
代码语言:javascript复制@Configuration
public class MvcConfig implements WebMvcConfigurer {
@Resource
private StringRedisTemplate stringRedisTemplate;
@Override
//添加拦截器 InterceptorRegistry registry 拦截器的注册器 excludePathPatterns排除不需要的拦截的路径
// 只要跟登录无关就不需要拦截 拦截器的作用只是校验登录状态
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LoginInterceptor())
.excludePathPatterns(
"/user/login",
"/user/code",
"/blog/hot",
"/shop/**",
"/shop-type/**",
"/voucher/**"
).order(1);
//order是设置先后
//刷新token的拦截器
registry.addInterceptor(new RefreshTokeninterceptor(stringRedisTemplate)).addPathPatterns("/**").order(0);
}
}


