当前位置: 首页 > news >正文

SpringBoot+Redis+Mybatis-plus黑马点评

短信登录

基于Session实现登录

流程:

发送短信验证码-->短信验证码注册登录-->校验登录状态(保存用户到ThreadLocal,方便后续使用)

不能每次请求服务都要进行登录状态校验,解决办法:拦截器

在Spring框架中,拦截器(Interceptor)可以通过实现HandlerInterceptor接口或继承HandlerInterceptorAdapter类来实现。拦截器通常用于在请求到达控制器之前进行预处理,例如身份验证、权限检查等。

1.创建拦截器(拦截器需要实现HandlerInterceptor接口,并重写方法)

2.注册拦截器(通过WebMvcConfigurer接口来注册拦截器。)

3.配置拦截器的排除路径(在实际应用中,某些接口(如登录、注册接口)不需要进行身份验证)

区分一下session,cookie和token

CookieCookie实际上是一小段的文本信息。客户端请求服务器,如果服务器需要记录该用户状态,就使用response向客户端浏览器颁发一个Cookie。客户端浏览器会把Cookie保存起来,服务不保存。每次请求时客户端带上cookie。服务器检查该Cookie,以此来辨认用户状态。

Session: 服务器在处理客户端请求过程中会创建session,并且为该session生存唯一的session ID。

服务器将session ID发送到客户端.当客户端再次请求时,就会带上这个session ID.服务器接收到请求之后就会一句Session ID 找到相应的Session ,完成请求.session是服务本地保存,发给客户端,客户端每次访问都带着,直接和服务的session比对

Token:Token是服务端生成的一串字符串,当作客户端进行请求的一个令牌,当第一次登录后,服务器生成一个Token并将此Token返回给客户端,以后客户端只需带上这个Token前来请求数据即可,无需再次带上用户名和密码.token是 服务经过计算发给客户端的,服务不保存,每次客户端来请求,经过解密等计算来验证是否是自己下发的.

JWT:JWT不仅仅是一个生成Token的过程,它还提供了一种结构化、自包含、无状态的Token设计。验证Token时,服务器不需要查询数据库,直接解析和验证签名即可。

机制

存储位置

通信方式

生命周期

Cookie

浏览器

自动Header携带

可设置过期时间

️ Session

服务端

SessionID传递

服务端控制

Token

客户端

手动Header添加

令牌有效期决定

️ JWT

客户端

Bearer Token

包含过期时间声明

集群Session共享问题

session的痛点(负载均衡导致的)

多态Tomcat并不共享session存储空间,当请求切换到不同tomcat服务时导致数据丢失的问题

基于Redis实现共享session登录

发送验证码逻辑实现:

1.校验手机号

2.不符合返回错误信息

3.符合生成验证码

4.保存验证码到redis

5.发送验证码

登录验证逻辑:

1.校验手机号

2.不符合返回错误信息

3.从redis中获取验证码并校验

4.不一致报错,一致,根据手机号查询用户

5.判断用户是否存在

6.保存用户信息到redis

6.1随机生成token,作为登录令牌

6.2将User对象转为Hash存储

6.3存储

7.返回token

登录拦截器的优化

拦截器:

1.获取token

2.查询Redis的用户

3.保存到ThreadLocal

4.刷新token有效器

5.放行

问题:

如果用户登录以后一直请求的是不需要拦截的请求,那么token有效期没有刷新,即使用户一直在使用,也没有做到token更新

解决办法:双拦截器

第一个拦截器拦截所有请求-->第二个拦截器拦截需要登录的请求

商户查询缓存

什么是缓存

缓存:数据交换的缓冲区,是存储数据的临时地方,一般读写性能毕竟高

浏览器(浏览器缓存)--->Redis(应用层缓存)--->数据库(数据库缓存)

缓存的作用:

1.降低后端负载 2.提高读写效率,降低相应时间

缓存的成本

1.数据一致性成本 2.代码维护成本 3.运维成本

添加Redis缓存

客户端请求优先到达缓存,如果缓存命中直接返回数据,如果未命中,请求数据库,并且写入缓存

缓存更新:

内存淘汰:不用自己维护,内存不足时自动淘汰部分数据

超时剔除:给缓存数据添加TTL时间,到期后自动删除缓存

主动更新:当涉及到数据库的增删改时,主动更新Redis缓存

主动更新策略:

1.在更新数据库的同时更新缓存------常用

2.数据库和缓存整合为一个服务,由服务来维护一致性

3.调用者只操作缓存,由其它线程异步的缓存数据持久到数据库,保证最终一致

操作缓存和数据库时有三个问题需要考虑:

1.删除缓存还是更新缓存?
2.如何保证缓存与数据库的操作同时成功或失败?

3.先操作缓存还是先操作数据库?

都有可能出现线程不安全的问题。 方案二的不安全几率更低---常用

缓存穿透

缓存穿透是指客户端请求的数据在缓存和数据库中都不存在,这样缓存永远不会生效,这些请求都会打到数据库。

常见的解决方案:

缓存空对象:缓存null

优点:实现简单,维护方便

缺点:额外的内存消耗,可能造成短期的不一致

布隆过滤:

客户端-->布隆过滤器-->Redis

布隆过滤器:利用hash存储数据库里的字段

优点:内存占用少,没有多余key

缺点:实现复杂,可能存在误判可能

缓存雪崩

在同一时段内大量的缓存key同时失效或者Redis服务宕机,导致大量请求到达数据库,带来巨大的压力

解决方案:

给不同的key的TTL添加随机值

利用Redis集群提高服务的可用性

给缓存业务添加降级限流策略

给业务添加多级缓存

缓存击穿

也叫热点Key问题,就是一个高并发访问并且缓存重建业务较复杂的key突然失效了,无效的请求访问会在瞬间给数据库带来巨大的冲击

常见的解决方案:

互斥锁

逻辑过期

缓存工具封装

方法1:将任意java对象序列化为json并存储在String类型的key中,并且可以设置TTL过期时间

方法2:将任意java对象序列化为json并存储在String类型的key中,并且可以设置逻辑过期时间,用于处理缓存击穿问题

方法3:根据指定的key查询缓存,并反序列化为指定类型,利用缓存空值的方式解决缓存穿透问题

方法4:根据指定的key查询缓存,并反序列化为指定类型,利用逻辑过期的方式解决缓存击穿问题

Public class CacheClient{private StringRedisTemplate stringRedisTemplate;public void set(String key, Object object,Long time,TimeUnit unit){StringRedisTemplate.opsForValue().set(key,JSONUTIL.toJsonStr(value),time,unit)}public void setWithLogicalExpire(String key, Object object,Long time,TimeUnit unit){//设置逻辑过期RedisData redisData = new RedisData();redisData.setData(value);redisData.setExpireTime(LocalDateTime.now().plusSeconds(unit.toSeconds(time)));StringRedisTemplate.opsForValue().set(key,JSONUTIL.toJsonStr(redisData))}public <R, ID> R queryWithPassThrough(Long time,TimeUnit unit,String keyPrefix, ID id, Class<R> type, Function<ID,R> dbFallback){String key = keyPrefix + id;//1.从Redis中查询商铺缓存String json = stringRedisTemplate.opsForValue().get(key);//2.判断是否存在if(StrUtil.isNotBlank(json)){return JSONUtil.toBean(json,type);}//3.判断命中的是否是空值is(json != null){return null;}//4.从数据库进行查询R r = dbFallback.apply(id);//5.不存在,返回错误if(r == null){//将空值写入redisstringRedisRemplate.opsForValue().set(key,"",null,TimeUnit.MINUTES);return null;}//6.存在,写入redisthis.set(key,r,time,unit);}public <R, ID> R queryWithLogicalExpire(String keyPrefix, ID id, Class<R> type, Function<ID, R> dbFallback, Long time, TimeUnit unit) {String key = keyPrefix + id;// 1.从Redis中查询缓存String json = stringRedisTemplate.opsForValue().get(key);// 2.判断是否存在if (StrUtil.isNotBlank(json)) {// 3.反序列化为RedisData对象RedisData redisData = JSONUtil.toBean(json, RedisData.class);R r = redisData.getData();LocalDateTime expireTime = redisData.getExpireTime();// 4.判断是否逻辑过期if (expireTime.isAfter(LocalDateTime.now())) {// 5.未过期,直接返回缓存数据return r;} else {// 6.已过期,更新缓存// 6.1 从数据库查询最新数据R latestData = dbFallback.apply(id);// 6.2 如果数据库中没有数据,返回nullif (latestData == null) {return null;}// 6.3 更新缓存RedisData newRedisData = new RedisData<>();newRedisData.setData(latestData);newRedisData.setExpireTime(LocalDateTime.now().plusSeconds(unit.toSeconds(time)));stringRedisTemplate.opsForValue().set(key, JSONUtil.toJsonStr(newRedisData));// 6.4 返回最新数据return latestData;}} else {// 7.缓存中没有数据,从数据库查询R r = dbFallback.apply(id);// 8.如果数据库中没有数据,返回nullif (r == null) {return null;}// 9.将数据写入缓存RedisData redisData = new RedisData<>();redisData.setData(r);redisData.setExpireTime(LocalDateTime.now().plusSeconds(unit.toSeconds(time)));stringRedisTemplate.opsForValue().set(key, JSONUtil.toJsonStr(redisData));// 10.返回查询结果return r;} }  
}

优惠劵秒杀

达人探店

好友关注

附近的商户

用户签到

UV统计

相关文章:

SpringBoot+Redis+Mybatis-plus黑马点评

短信登录 基于Session实现登录 流程&#xff1a; 发送短信验证码-->短信验证码注册登录-->校验登录状态&#xff08;保存用户到ThreadLocal&#xff0c;方便后续使用&#xff09; 不能每次请求服务都要进行登录状态校验&#xff0c;解决办法&#xff1a;拦截器 在Sp…...

深入剖析 OpenCV:全面掌握基础操作、图像处理算法与特征匹配

深入剖析 OpenCV&#xff1a;全面掌握基础操作、图像处理算法与特征匹配 一、引言二、OpenCV 的安装&#xff08;一&#xff09;使用 pip 安装&#xff08;二&#xff09;使用 Anaconda 安装 三、OpenCV 基础操作&#xff08;一&#xff09;图像的读取、显示与保存&#xff08;…...

【C语言显示Linux系统参数】

在C语言中&#xff0c;可以通过调用Linux系统提供的API来获取和显示系统参数。以下是一些常见的系统参数及其获取方法&#xff1a; 1. 获取系统名称和版本 可以使用uname函数来获取系统名称、版本等信息。 #include <stdio.h> #include <sys/utsname.h>int main…...

突破Ajax跨域困境,解锁前端通信新姿势

一、引言 在当今的 Web 开发领域&#xff0c;前后端分离的架构模式已经成为主流&#xff0c;它极大地提升了开发效率和项目的可维护性。在这种开发模式下&#xff0c;前端通过 Ajax 技术与后端进行数据交互&#xff0c;然而&#xff0c;跨域问题却如影随形&#xff0c;成为了开…...

Kotlin协变与逆变区别

在Kotlin中&#xff0c;协变和逆变是泛型编程中的两个重要概念&#xff0c;它们允许我们在类型系统中更加灵活地处理类型关系。 1.协变&#xff1a;协变允许我们使用比原始类型更具体的类型。在kotlin中&#xff0c;通过在类型参数上加out关键字来表示协变,生产者&#xff0c;例…...

driver中为什么要使用非阻塞赋值

1. 模拟硬件时序行为 实际硬件行为&#xff1a;DUT的输入信号通常在时钟边沿被采样。Driver需要确保信号的更新与时钟同步&#xff0c;而非阻塞赋值的延迟更新特性&#xff08;在时间步结束时统一生效&#xff09;能够准确模拟寄存器的行为。 示例&#xff1a; always (posedg…...

模板字符串【ES6】

“路漫漫其修远兮&#xff0c;吾将上下而求索。”—— 屈原《离骚》 目录 什么是模板字符串&#xff1f;模板字符串特性及代码举例&#xff1a;详细举例用法&#xff1a; 什么是模板字符串&#xff1f; 模板字符串&#xff08;Template Literals&#xff09;是JavaScript中引入…...

通往 AI 之路:Python 机器学习入门-数据结构

Python 数据结构 Python 提供了多种数据结构来存储和操作数据&#xff0c;其中列表&#xff08;list&#xff09;、字典&#xff08;dict&#xff09;、元组&#xff08;tuple&#xff09;和集合&#xff08;set&#xff09;是最常用的几种。本章将详细介绍这些数据结构的基本…...

我们应该如何优化UI(基于UGUI)

这是一道面试题&#xff0c;下面&#xff0c;我们来详细分析这个问题。 目录 1. 减少 Draw Call 合理设置图集 避免材质和 Shader 的频繁切换 减少 UI 元素的重叠 2. 优化UI布局 3. 优化UI元素的渲染 4.优化UI动画 5. 优化 UI 事件处理 6. 运行时优化 1. 减少 Draw C…...

CSS3 圆角:实现与优化指南

CSS3 圆角&#xff1a;实现与优化指南 随着网页设计的发展&#xff0c;CSS3 圆角已经成为了现代网页设计中不可或缺的元素之一。本文将详细讲解 CSS3 圆角的基本用法、实现方式以及优化技巧&#xff0c;帮助您在网页设计中更好地运用这一功能。 一、CSS3 圆角基本用法 1.1 基…...

【网络安全 | 扫描子域+发现真实IP】CloakQuest3r安装使用详细教程

原创文章,禁止转载。 本文仅作学习交流使用,不得用于非法渗透,笔者不承担任何责任。 文章目录 简介功能介绍执行流程限制安装步骤可选功能:SecurityTrails API使用示例简介 CloakQuest3r 是一款强大的 Python 工具,专为揭示受 Cloudflare 及类似服务保护的网站真实 IP 地…...

Mellanox OFED驱动如何给全局编译添加gcc的编译选项?(subdir-ccflags-y += -Wall)

背景 有些时候编译驱动需要给全局加一个编译选项&#xff0c;假设configure已经完成。可以直接在Makefile中修改 添加方式 修改OFED驱动目录下的&#xff1a; ./Makefile subdir-ccflags-y -Wall修改效果&#xff1a; 然后执行make&#xff0c;就能让添加的编译选项生效…...

【愚公系列】《Python网络爬虫从入门到精通》037-文件的存取

标题详情作者简介愚公搬代码头衔华为云特约编辑,华为云云享专家,华为开发者专家,华为产品云测专家,CSDN博客专家,CSDN商业化专家,阿里云专家博主,阿里云签约作者,腾讯云优秀博主,腾讯云内容共创官,掘金优秀博主,亚马逊技领云博主,51CTO博客专家等。近期荣誉2022年度…...

【一起学Rust | Tauri2.0框架】单实例应用程序的深入解析:零漏洞实现与优化实战

文章目录 前言一、 单实例应用的意义二、 实现单实例应用的方法1 Windows下的实现1.1 创建命名Mutex1.2 在Tauri应用中集成Mutex检查 2 macOS下的实现2.1 获取Bundle Identifier2.2 检查是否已经有实例在运行 3 Linux下的实现3.1 获取进程列表3.2 检查是否已经有实例在运行 4 在…...

PhyloSuite v1.2.3安装与使用-生信工具049

PhyloSuite 一个好用的win集成建树平台&#xff0c;官方相关文档视频等做的可好了PhyloSuite (jushengwu.com) 官网 https://github.com/dongzhang0725/PhyloSuite/releases #官网 http://phylosuite.jushengwu.com/dongzhang0725.github.io/installation/ #官方说明文档…...

使用Apache Lucene构建高效的全文搜索服务

使用Apache Lucene构建高效的全文搜索服务 在现代应用程序中&#xff0c;全文搜索功能是不可或缺的一部分。无论是电子商务网站、内容管理系统&#xff0c;还是数据分析平台&#xff0c;快速、准确地搜索大量数据是提升用户体验的关键。Apache Lucene 是一个强大的全文搜索引擎…...

SSH远程登录并执行命令

SSH远程登录并执行命令 1、登录远程服务器2、远程执行命令3、远程执行交互命令4、远程执行脚本5、退出远程SSH连接 SSH是Linux中的远程连接管理工具&#xff0c;可以在本地服务器上通过SSH协议连接到远程服务器&#xff0c;并在远程服务器上执行命令 SSH不仅可以用来登录远程服…...

EasyRTC:支持任意平台设备的嵌入式WebRTC实时音视频通信SDK解决方案

随着互联网技术的飞速发展&#xff0c;实时音视频通信已成为各行各业数字化转型的核心需求之一。无论是远程办公、在线教育、智慧医疗&#xff0c;还是智能安防、直播互动&#xff0c;用户对低延迟、高可靠、跨平台的音视频通信需求日益增长。 一、WebRTC与WebP2P&#xff1a;实…...

Golang语言特性

1.Go语言的优势 1.1极简单的部署方式 —可以直接编译成机器码。代码可以直接转换为二进制数据&#xff0c;在操作系统上可以直接./去执行。 —不依赖其他库。最终生成的可执行程序是一个静态的二进制文本文件。 —可以直接运行即可部署。 —静态类型语言。编译的时候检查出来隐…...

LangPrompt提示词

LangPrompt提示词 https://github.com/langgptai/LangGPT 学习LangGPT的仓库&#xff0c;帮我创建 一个专门生成LangGPT格式prompt的助手 根据LangGPT的格式规范设计的专业提示词生成助手框架。以下是分步骤的解决方案&#xff1a; 助手角色定义模板 # Role: LangGPT提示词架…...

RestClient

什么是RestClient RestClient 是 Elasticsearch 官方提供的 Java 低级 REST 客户端&#xff0c;它允许HTTP与Elasticsearch 集群通信&#xff0c;而无需处理 JSON 序列化/反序列化等底层细节。它是 Elasticsearch Java API 客户端的基础。 RestClient 主要特点 轻量级&#xff…...

多云管理“拦路虎”:深入解析网络互联、身份同步与成本可视化的技术复杂度​

一、引言&#xff1a;多云环境的技术复杂性本质​​ 企业采用多云策略已从技术选型升维至生存刚需。当业务系统分散部署在多个云平台时&#xff0c;​​基础设施的技术债呈现指数级积累​​。网络连接、身份认证、成本管理这三大核心挑战相互嵌套&#xff1a;跨云网络构建数据…...

DockerHub与私有镜像仓库在容器化中的应用与管理

哈喽&#xff0c;大家好&#xff0c;我是左手python&#xff01; Docker Hub的应用与管理 Docker Hub的基本概念与使用方法 Docker Hub是Docker官方提供的一个公共镜像仓库&#xff0c;用户可以在其中找到各种操作系统、软件和应用的镜像。开发者可以通过Docker Hub轻松获取所…...

【Java学习笔记】Arrays类

Arrays 类 1. 导入包&#xff1a;import java.util.Arrays 2. 常用方法一览表 方法描述Arrays.toString()返回数组的字符串形式Arrays.sort()排序&#xff08;自然排序和定制排序&#xff09;Arrays.binarySearch()通过二分搜索法进行查找&#xff08;前提&#xff1a;数组是…...

数据库分批入库

今天在工作中&#xff0c;遇到一个问题&#xff0c;就是分批查询的时候&#xff0c;由于批次过大导致出现了一些问题&#xff0c;一下是问题描述和解决方案&#xff1a; 示例&#xff1a; // 假设已有数据列表 dataList 和 PreparedStatement pstmt int batchSize 1000; // …...

【开发技术】.Net使用FFmpeg视频特定帧上绘制内容

目录 一、目的 二、解决方案 2.1 什么是FFmpeg 2.2 FFmpeg主要功能 2.3 使用Xabe.FFmpeg调用FFmpeg功能 2.4 使用 FFmpeg 的 drawbox 滤镜来绘制 ROI 三、总结 一、目的 当前市场上有很多目标检测智能识别的相关算法&#xff0c;当前调用一个医疗行业的AI识别算法后返回…...

零基础在实践中学习网络安全-皮卡丘靶场(第九期-Unsafe Fileupload模块)(yakit方式)

本期内容并不是很难&#xff0c;相信大家会学的很愉快&#xff0c;当然对于有后端基础的朋友来说&#xff0c;本期内容更加容易了解&#xff0c;当然没有基础的也别担心&#xff0c;本期内容会详细解释有关内容 本期用到的软件&#xff1a;yakit&#xff08;因为经过之前好多期…...

短视频矩阵系统文案创作功能开发实践,定制化开发

在短视频行业迅猛发展的当下&#xff0c;企业和个人创作者为了扩大影响力、提升传播效果&#xff0c;纷纷采用短视频矩阵运营策略&#xff0c;同时管理多个平台、多个账号的内容发布。然而&#xff0c;频繁的文案创作需求让运营者疲于应对&#xff0c;如何高效产出高质量文案成…...

【C++进阶篇】智能指针

C内存管理终极指南&#xff1a;智能指针从入门到源码剖析 一. 智能指针1.1 auto_ptr1.2 unique_ptr1.3 shared_ptr1.4 make_shared 二. 原理三. shared_ptr循环引用问题三. 线程安全问题四. 内存泄漏4.1 什么是内存泄漏4.2 危害4.3 避免内存泄漏 五. 最后 一. 智能指针 智能指…...

Proxmox Mail Gateway安装指南:从零开始配置高效邮件过滤系统

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐&#xff1a;「storms…...