🍎前言
🍐项目的背景
背景:🍉当我们在完成用户信息登录时,我们往往每次都会在数据库中查询用户的记录,生成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: localhostport: 6379password: 123456database: 1timeout: 3000ms #最大等待时间,超时则抛出异常,否则请求一直等待lettuce:pool:max-active: 20 #最大连接数,负值表示没有限制,默认8max-wait: -1 #最大阻塞等待时间,负值表示没限制,默认-1max-idle: 8 #最大空闲连接,默认8min-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类型的redisHashOperations hashOperations = redisTemplate.opsForHash();// hash最外层的keyString hashKey = Constants.REDIS_USER_INFO_CACHE.getValue();// 用户信息UserLoginVO userInfo = null;// 这里做的是账号密码登录所操作的数据if (object instanceof UserDTOLogin userDTOLogin) {hashKey += userDTOLogin.getUserName();// 找到用户信息直接returnif (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;}// 不是目标对象直接返回nullreturn 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缓存中读取用户的数据,直接返回。这样就减轻了数据库的压力,以及服务器的压力。
如有问题,欢迎在下方评论区留言,感谢大家的支持,给个三连呗~🍒
欢迎大家关注我的微信公众号,里面分享了更多的开发技巧?