redis常用场景——缓存登录信息

场景重现


当一个boot程序开启拦截器,那么每次拦截请求都需要通过 mysql 查询用户信息,这样会给服务器带来很大的负担,此时可以使用 redis 作为中间件,缓存登录信息

优点:

  • redis 内存读写,速度快

没使用redis缓存前

使用 redis 缓存后

环境准备


  • springboot
  • redis
  • mysql

springboot 的 application.yaml 如下:

  data:  
    redis:  
      host: localhost
      port: 6379  
      password: ********  
      lettuce:  
        pool:  
          max-active: 10  
          max-idle: 10  
          min-idle: 1  
          time-between-eviction-runs: 10s  
  datasource:  
    driver-class-name: com.mysql.cj.jdbc.Driver  
    url: jdbc:mysql://localhost:3306/xxx?useSSL=false&serverTimezone=UTC  
    username: hmdp  
    password: 2fjR8hnYzEh4Rik6  
  jackson:  
    default-property-inclusion: non_null # JSON处理时忽略非空字段  
mybatis-plus:  
  type-aliases-package: com.hmdp.entity # 别名扫描包  
logging:  
  level:  
    com.hmdp: debug

实现步骤


1. 在原本的业务代码中加入如下逻辑代码

@Resource  
private StringRedisTemplate stringRedisTemplate;
@Override  
public Result login(LoginFormDTO loginForm, HttpSession session) {  
    // 1. 校验手机号和验证码 
    .......
  
    // 2. 从Redis中获取验证码并校验  
    String cacheCode = stringRedisTemplate.opsForValue().get(LOGIN_CODE_KEY + phone);  
    String code = loginForm.getCode();  
    if (cacheCode == null || !cacheCode.equals(code)) {  
        // 不一致,错误  
        return Result.fail("验证码错误");  
    }  
  
    // 3. 根据手机号查询用户  
......
  
    // 5. 存入 redis  
    // 5.1 生成随机token    String token = UUID.randomUUID().toString(true);  
    // 5.2 将 User 对象转换为DTO  
    UserDTO userDTO = BeanUtil.copyProperties(user, UserDTO.class);  
    Map<String, Object> userMap = BeanUtil.beanToMap(userDTO, new HashMap<>(),  
            CopyOptions.create()  
                    .setIgnoreNullValue(true)  
                    .setFieldValueEditor((s, o) -> o.toString()));  
    // 5.3 存储  
    String tokenKey = LOGIN_USER_KEY + token;  
    stringRedisTemplate.opsForHash().putAll(tokenKey, userMap);  
    // 5.4 设置过期时间  
    stringRedisTemplate.expire(tokenKey, LOGIN_USER_TTL, TimeUnit.MINUTES);  
  
    return Result.ok(token);  
}

2.添加拦截器

public class RefreshInterceptor implements HandlerInterceptor {  
  
    private final StringRedisTemplate stringRedisTemplate;  
  
    public RefreshInterceptor(StringRedisTemplate stringRedisTemplate) {  
        this.stringRedisTemplate = stringRedisTemplate;  
    }  
  
    @Override  
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {  
        // 1.获取请求头中的token  
        String token = request.getHeader("authorization");  
        if (StringUtils.isBlank(token)) {  
           return true;  
        }  
        // 2.从TOKEN获取redis中的用户  
        Map<Object, Object> userMap = stringRedisTemplate.opsForHash()  
                .entries(RedisConstants.LOGIN_USER_KEY + token);  
        // 3.判断用户是否存在  
        if (userMap.isEmpty()) {  
            return true;  
        }  
        // 5.将查询到的Hash数据转换为DTO对象  
        UserDTO userDTO = BeanUtil.fillBeanWithMap(userMap, new UserDTO(), false);  
        // 6. 存在,将信息保存到ThreadLocal  
        UserHolder.saveUser(userDTO);  
        // 7. 刷新 token 有效期  
        stringRedisTemplate.expire(RedisConstants.LOGIN_USER_KEY + token, RedisConstants.LOGIN_CODE_TTL, TimeUnit.MINUTES);  
        return true;  
    }  
  
    @Override  
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {  
        // 移除用户  
        UserHolder.removeUser();  
    }  
}
public class LoginInterceptor implements HandlerInterceptor {  
  
    @Override  
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {  
        // 1. 判断是否需要拦截  
        if (UserHolder.getUser() == null) {  
            // 没有,需要拦截  
            response.setStatus(401);  
            return false;  
        }  
        // 有用户,放行  
        return true;  
    }  
  
}
@Configuration  
public class MvcConfig implements WebMvcConfigurer {  
  
    @Resource  
    private StringRedisTemplate stringRedisTemplate;  
  
    @Override  
    public void addInterceptors(InterceptorRegistry registry) {  
        // 登录拦截器  
        registry.addInterceptor(new LoginInterceptor()).excludePathPatterns(  
                "/shop/**",  
                "/voucher/**",  
                "/shop-type/**",  
                "/upload/**",  
                "/blog/hot",  
                "/user/code",  
                "/user/login"  
        ).order(1);  
        // 刷新拦截器  
        registry.addInterceptor(new RefreshInterceptor(stringRedisTemplate)).addPathPatterns("/**").order(0);  
  
    }  
}
  • 10
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值