双拦截器:全局拦截器当“打卡机”负责所有请求的无感续期,权限拦截器当“安检门”只查ThreadLocal守护核心业务,两者完美实现了性能与用户体验的职责分离。

RefreshTokenInterceptor刷新token有效期 优先级最高
java
/**
* 执行preHandle相关业务逻辑。
*
* 作用:
* 1.获取请求头中的token;
* 2.基于token获取Redis中的用户;
* 3.判断用户是否存在;
* 4.将查询到的hash数据转为UserDTO;
* 5.存在,保存用户信息到ThreadLocal;
*
* @param request request参数
* @param response response参数
* @param handler handler参数
* @return处理结果
*/
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//获取请求头中的token
String token=request.getHeader("authorization");
if(StrUtil.isBlank(token)){
return true;
}
//基于token获取Redis中的用户
String key=RedisConstants.LOGIN_USER_KEY+token;
Map<Object,Object> userMap=stringRedisTemplate.opsForHash().entries(key);
//判断用户是否存在
if(userMap.isEmpty()){
return true;
}
//将查询到的hash数据转为UserDTO
UserDTO userDTO= BeanUtil.fillBeanWithMap(userMap,new UserDTO(),false);
//存在,保存用户信息到ThreadLocal
UserHolder.saveUser(userDTO);
//刷新了token有效期
stringRedisTemplate.expire(key,RedisConstants.LOGIN_USER_TTL, TimeUnit.MINUTES);
//放行
return true;
}LoginInterceptor权限判断
java
/**
* 执行preHandle相关业务逻辑。
*
* 作用:
* 1.没有,需要拦截,设置状态码;
* 2.拦截;
* 3.有用户,则放行;
*
* @param request request参数
* @param response response参数
* @param handler handler参数
* @return处理结果
*/
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
if(UserHolder.getUser()==null){
//没有,需要拦截,设置状态码
response.setStatus(401);
//拦截
return false;
}
//有用户,则放行
return true;
}- MvcConfig
java
/**
* 注册登录拦截器。
*
* @param registry registry参数
* @return无返回值
*/
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LoginInterceptor())
.excludePathPatterns(
"/user/code",
"/user/login",
"/blog/hot",
"/shop/**",
"/shop-type/**",
"/voucher/**",
"/upload/**"
).order(1);
registry.addInterceptor(new RefreshTokenInterceptor(stringRedisTemplate)).addPathPatterns("/**").order(0);
}