SpringBoot + Redis实现用户信息登录的缓存

🍎前言

🍐项目的背景

背景:🍉当我们在完成用户信息登录时,我们往往每次都会在数据库中查询用户的记录,生成token并返回给前端,不过这样会有一定的问题。

🍐造成的问题

问题:🍉每次都需要访问数据库进行查询操作,是否显得麻烦,是否会给数据库造成一定的压力?

🍐解决的方案

解决方案:🍉我们通过实现redis数据库进行用户数据的缓存,并且设置一下缓存的过期时间,从而下次再登录时,就能从redis数据库缓存中获取数据了

🍎项目的版本

🍉jdk:17

🍉springboot:3.0.2

🍉redis版本:5.0.14

🍉maven版本:3.8.8

🍉idea版本:2023

🍐引入相关依赖

我们再pom.xml引入一下redis的依赖

 <!--        redis-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>

在application.yaml配置文件配置一下redis数据库的依赖

spring:
  data:
    redis:
      host: localhost
      port: 6379
      password: 123456
      database: 1
      timeout: 3000ms #最大等待时间,超时则抛出异常,否则请求一直等待
      lettuce:
        pool:
          max-active: 20  #最大连接数,负值表示没有限制,默认8
          max-wait: -1    #最大阻塞等待时间,负值表示没限制,默认-1
          max-idle: 8     #最大空闲连接,默认8
          min-idle: 0     #最小空闲连接,默认0

🍉注意:想要使用redis做缓存,我们必须得把我们相关的实体类实现一个序列化接口为Serializable

否则无法存储在redis中

🍎创建控制层

🍉这里我就以用户的账号和密码做登录来查询用户数据。

🌕这里先上代码,我们下面的几个对象一个个做说明

🍉redisTemplate:创建了redis模板对象

🍉userService:对user的业务层,里面写了根据用户名和密码查询用户的信息

🍉fileUploadUtil:文件上传的工具类,这里不展开讲

下面是重点了

🍉redisCacheUtils:创建了一个用于获取redis中数据缓存的工具类对象,这个后面再讲

🌕在我们的/login的接口部分中使用redisCacheUtils调用了一个方法,并且传递了以下三个对象

分别是:

🍉redisTemplate

🍉userService

🍉userDTOLogin

🌕注意:为什么需要这么传呢?由于登录的方式可能不止这一个,我们可能有许多的登陆方式,但是每次传递的最后一个参数实体类对象不一致,所以存储的key也会有相应的变化

@RestController
@RequestMapping("/pcClientUser/Login")
@Slf4j
@RequiredArgsConstructor
public class LoginController {
    // redis模板对象
    private final RedisTemplate redisTemplate;
    // user相关的业务层
    private final UserService userService;
    // 文件上传工具类
    private final FileUploadUtil fileUploadUtil;
    // 创建用户获取redis中数据缓存的工具类
    private final RedisCacheUtils redisCacheUtils;   

/**
     * 用户账号密码登录
     *
     * @param userDTOLogin
     * @return
     */
    @PostMapping("/login")
    public Result Login(@RequestBody UserDTOLogin userDTOLogin) {
        log.info("用户登录");
        UserLoginVO userInfo = redisCacheUtils.FindRedisCacheUserInfo(redisTemplate, userService, userDTOLogin);
        return Result.success(Constants.LOGIN.getValue(), userInfo);
    }
}

🍉这里是我的UserDtoLogin的代码,这里面的也就是前端传过来的账号密码

package com.sxy.recordnetwork.DTO.USER;

import lombok.*;

@NoArgsConstructor
@AllArgsConstructor
@Data
@ToString
@Builder
public class UserDTOLogin {
    // 账号
    private String userName;
    // 密码
    private String passWord;

}

🍉接下类我们来看看redisCacheUtils这个类里面有什么奇妙之处吧?

🍎创建一个redisCacheUtils工具类

package com.sxy.recordnetwork.Utils;

import com.sxy.recordnetwork.DTO.USER.UserDTOLogin;
import com.sxy.recordnetwork.DTO.USER.UserDtoEmailLogin;
import com.sxy.recordnetwork.DTO.USER.UserDtoPhoneLogin;
import com.sxy.recordnetwork.VO.User.UserLoginVO;
import com.sxy.recordnetwork.common.Result;
import com.sxy.recordnetwork.enumeration.Constants;
import com.sxy.recordnetwork.service.UserService;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.util.concurrent.TimeUnit;

/**
 * redis缓存相关操作的工具类
 */
@Component
public class RedisCacheUtils {


    /**
     * 一个用于存储在redis中的用户信息的工具类,适用于所有登录的共同抽离方法
     * 该方法用于从redis中获取用户信息
     *
     * @param redisTemplate
     * @param object
     * @return
     */
    public UserLoginVO FindRedisCacheUserInfo(RedisTemplate redisTemplate, UserService userService, Object object) {
        // 操作hash类型的redis
        HashOperations hashOperations = redisTemplate.opsForHash();
        // hash最外层的key
        String hashKey = Constants.REDIS_USER_INFO_CACHE.getValue();
        // 用户信息
        UserLoginVO userInfo = null;
        // 这里做的是账号密码登录所操作的数据
        if (object instanceof UserDTOLogin userDTOLogin) {
            hashKey += userDTOLogin.getUserName();
            // 找到用户信息直接return
            if (hashOperations.get(hashKey, userDTOLogin.getUserName()) != null) {
                // 转为用户对象
                userInfo = (UserLoginVO) hashOperations.get(hashKey, userDTOLogin.getUserName());
                // 直接返回给前端
                return userInfo;
            }
            // redis中不存在目标用户的数据情况
            // 通过数据库查询用户数据
            userInfo = userService.Login(userDTOLogin);
            // 并且将用户数据存储到redis数据库中
            hashOperations.put(hashKey, userDTOLogin.getUserName(), userInfo);
            // 设置过期时间
            redisTemplate.expire(hashKey, 7200000, TimeUnit.SECONDS);
            return userInfo;
        }
        
        // 不是目标对象直接返回null
        return null;
    }

}

🍉这个类里有一个FindRedisCacheUserInfo这个方法,也就是我控制层调用的这个方法

🍉方法中有三个参数,分别是:redisTemplate模板对象,userService对象,和object对象

🍉这个object对象很有用处。是用来根据不同登录,传递不同的对象来做类型的判断,对不同的登录操作进行存储不同的key和值

🍉首先我们通过redis模板创建一个hash类型的redis

🍉接着有一个最外层的key就是获取hash的key这里有定义为一个枚举类,具体内容可以随意加

🍉创建了一个用户信息UserLoginVo,这里的用户信息就是所有登录之后查询的用户信息进行返回

🍉接下来进行instanceof关键字的类型判断,

🍉判断传过来的类型是否是UserDTOLogin对象,是则创建该对象

🍉得到hashkey对用户名进行拼接得到一个唯一key,我这里的用户名是唯一的所以不用担心会重复

🍐用户信息不存在redis中的情况

🍉这里直接通过对象的参数,查询用户信息的方法。

🍉将用户信息存储到redis中设置hashkey进行put数据

🍉参数列表为(hash唯一key,field为用户名,数据为用户信息)

🍉直接通过redisTemplate对象属性.expire为指定的key设置过期时间

🍉参数列表为:key,时间,单位

🍉返回给控制层视图,最后控制层视图就直接返回数据给前端

🍐用户信息存在redis中的情况

🍉通过hash类型.get方法传入指定参数得到数据

🍉参数列表:hash唯一key,field为用户名

🍉查出来:不等于空就通过key和field,查询redis的用户的信息转为UserLoginVo对象

🍉返回给控制层视图,最后控制层视图就直接返回数据给前端

🍎总结

🍉以上就是今天分享的内容,在用户登录时将数据存储到redis缓存中,下次登录就无需直接访问mysql数据库层,而是直接从redis缓存中读取用户的数据,直接返回。这样就减轻了数据库的压力,以及服务器的压力。

如有问题,欢迎在下方评论区留言,感谢大家的支持,给个三连呗~🍒

欢迎大家关注我的微信公众号,里面分享了更多的开发技巧?

评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

树若逝花若殇

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值