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缓存中读取用户的数据,直接返回。这样就减轻了数据库的压力,以及服务器的压力。

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

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/557921.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Linux 用户和组

理解Linux 用户和组的概念 掌握passwd 文件的组成以及作用 掌握shadow 文件的组成以及作用 了解group 文件的内容 1.用户分类&#xff1a; 超级管理员&#xff08;root&#xff09; 普通用户 程序用户 1.用户信息文件 /etc/passwd 文件中存储了所有用户信息。 1.passwd 格…

python中中英文打印对齐解决方案

在python中&#xff0c;有时候会出现中英文混合输出的情形&#xff0c;但是由于中文默认是全角格式&#xff08;一个中文字符占用两个字符宽度&#xff09;&#xff0c;这会对python原生的print函数带来一些障碍。尤其是用户用print对齐输出的时候&#xff0c;这种差异会导致文…

月球地形数据介绍(LOLA)

月球地形数据介绍 LOLA介绍LOLA数据的处理与发布数据类型和格式投影坐标系SIMPLE CYLINDRICALPOLAR STEREOGRAPHIC 数据下载与浏览 LOLA介绍 目前最新的月球地形高程数据来源于美国2009年发射的LRO探测器。 “月球勘测轨道器”(Lunar Reconnaissance Orbiter&#xff0c;LRO)…

文心一言 VS 讯飞星火 VS chatgpt (240)-- 算法导论17.3 6题

六、证明&#xff1a;如何用两个普通的栈实现一个队列(练习10.1-6)&#xff0c;使得每个 ENQUEUE 和 DEQUEUE 操作的摊还代价为 O(1) 。练习10.1-6的内容是&#xff1a;说明如何用两个栈实现一个队列&#xff0c;并分析相关队列操作的运行时间。如果要写代码&#xff0c;请用go…

【MIT6.824】lab2C-persistence, lab2D-log compaction 实现笔记

引言 lab2C的实验要求如下 Complete the functions persist() and readPersist() in raft.go by adding code to save and restore persistent state. You will need to encode (or “serialize”) the state as an array of bytes in order to pass it to the Persister. Us…

el-table使用show-summary合计,但只需要合并某一列

el-table使用show-summary合计&#xff0c;但只需要合并某一列 这里有两种方法&#xff0c;一种是网上的&#xff0c;我会引用他的链接给你们看。 一种是我自己看源码发现的 方法一 这个就是方法一的链接 点击我跳转方法一 方法二 不需要计算的列 去掉prop 然后用插槽显示即可…

比特币叙事大转向

作者&#xff1a;David Lawant 编译&#xff1a;秦晋 要理比特币解减半动态&#xff0c;最关键的图表是下面这张&#xff0c;而不是价格图表。它显示了自 2012 年以来&#xff0c;矿业总收入与比特币现货交易量的比例&#xff0c;并标注了三个减半日期。 虽然矿工仍然是比特币生…

Python八股文:基础知识Part2

1. Python中变量的保存和访问 Python中的变量实际上是一个指向对象的引用&#xff0c;每个对象都有一个唯一的标识符&#xff08;即内存地址&#xff09;。对于一些不可变对象&#xff0c;如字符串和整数&#xff0c;因为它们的值不可更改&#xff0c;所以当多个变量引用相同的…

OSPF大型实验

OSPF大型实验 实验拓扑图 实验思路 1、R4为ISP&#xff0c;其上只配置IP地址&#xff1b;R4与其他所直连设备间均使用公有IP&#xff1b; 2、R3-R5、R6、R7为MGRE环境&#xff0c;R3为中心站点&#xff1b; 3、整个OSPF环境IP基于172.16.0.0/16划分&#xff1b;除了R12有两…

Java精品项目--第8期基于SpringBoot的宠物用品商城的设计分析与实现

项目使用技术栈 SpringBootThymeleafMyBatisMySQLAopJavajdk1.8 项目介绍 项目截图

JAVA 集合框架(一) Collection集合详解和常用方法

Java集合框架&#xff08;Java Collections Framework&#xff09;是一个强大的、高度灵活的数据结构库&#xff0c;它为Java应用程序提供了组织、存储和操作对象集合的标准方法。 集合类体系结构 接口类&#xff1a; Collection: 是单例集合类的顶层接口&#xff0c;包括Lis…

移动端适配之viewport

目录 盒模型&#xff1a;widthcontent&#xff08;padding border&#xff09; class"content-box"内容盒模型&#xff08;W3C盒&#xff09; class"border-box"边框盒模型&#xff08;IE 盒&#xff09; scroll滚动 window浏览器视窗&#xff1a;包括…

MySQL高级(索引-性能分析-explain执行计划)

explain 或者 desc 命令获取 MySQL 如何执行 select 语句的信息&#xff0c;包括在 select 语句执行过程中表如何连接和连接的顺序。 -- 直接在 select 语句之前加上关键字 explain / desc explain select 字段列表 from 表名 where 条件 &#xff1b; explain select * …

自养号测评:如何提高国际站,敦煌网的店铺销量?

随着互联网技术的迅猛进步&#xff0c;电子商务已经成为现代商业领域中不可或缺的一环。敦煌网&#xff0c;作为专注于中国文化艺术产品的电商平台&#xff0c;成功吸引了大量消费者的目光。然而&#xff0c;对于商家而言&#xff0c;如何进一步提升敦煌网的销售业绩&#xff0…

用这些工具搭建企业内部知识库,原来这么轻松

在快速发展和信息爆炸的时代&#xff0c;为企业构建一个内部知识库变得十分重要。它不仅有助于保存关键信息&#xff0c;促进知识传承&#xff0c;还能提高企业的整体效率和响应能力。今天&#xff0c;我们将探讨三款非常适合搭建企业内部知识库的工具&#xff0c;它们各具特色…

Python教学入门:流程控制

条件语句&#xff08;if 语句&#xff09;&#xff1a; 条件语句用于根据条件的真假执行不同的代码块。 x 10if x > 0: # 如果 x 大于 0print("x 是正数") # 输出&#xff1a;x 是正数 elif x 0: # 如果 x 等于 0print("x 是零") else: # 如果以…

第07-1章 计算机网络相关概念

7.1 本章目标 了解网络协议的概念了解网络体系结构熟悉ISO/OSI参考模型以及每一层的功能掌握TCP/IP模型各层的主要协议及其功能熟练掌握IP地址、子网规划等相关内容 7.2 网络协议的概念 7.2.1 概念介绍 &#xff08;1&#xff09;网络协议&#xff1a;计算机网络和分布系统中…

Java 笔试强训篇- Day1

&#x1f525;博客主页&#xff1a; 【小扳_-CSDN博客】 ❤感谢大家点赞&#x1f44d;收藏⭐评论✍ 文章目录 1.0 点击消除 1.1 解题思路一 1.2 解题思路二 2.0 在两个数组中找出相同的数 2.1 解题思路 笔试强训说明&#xff1a;有一些题目提供不了原题。 1.0 点击消除 该题链…

初学python记录:力扣1883. 准时抵达会议现场的最小跳过休息次数

题目&#xff1a; 给你一个整数 hoursBefore &#xff0c;表示你要前往会议所剩下的可用小时数。要想成功抵达会议现场&#xff0c;你必须途经 n 条道路。道路的长度用一个长度为 n 的整数数组 dist 表示&#xff0c;其中 dist[i] 表示第 i 条道路的长度&#xff08;单位&…

Redis之路系列(2)纸上得来终觉浅(上)

02 纸上得来终觉浅(上) 文章内容基于redis6&#xff0c;本章节介绍了redis的实际应用&#xff0c;主要包含&#xff1a;大量键值对保存的案例场景&#xff0c;海量key时的聚合计算、排序计算、状态统计、基础统计的应用 大量键值对保存 场景案例 有这么一个需求场景&#xff…