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

【开发篇】十、Spring缓存:手机验证码的生成与校验

文章目录

  • 1、缓存
  • 2、用HashMap模拟自定义缓存
  • 3、SpringBoot提供缓存的使用
  • 4、手机验证码案例完善

1、缓存

  • 缓存是一种介于数据永久存储介质与数据应用之间的数据临时存储介质
  • 使用缓存可以有效的减少低速数据读取过程的次数(例如磁盘IO),提高系统性能
  • 缓存不仅可以用于提高永久性存储介质的数据读取效率,还可以提供临时的数据存储空间

在这里插入图片描述

注意最后这条,缓存的不一定就是从持久层数据库来的数据,也可以是程序运行的临时数据,理解别太狭义,如手机验证码,对应于下图的Cache1:

在这里插入图片描述

2、用HashMap模拟自定义缓存

传统的一个查询接口,每次都查需要去和数据库交互,数据库压力大且容易产生性能瓶颈:

在这里插入图片描述
在这里插入图片描述

在Service层引入一个Map类型的非局部变量,来模拟缓存:(这种使用一个Map来充当临时缓冲池的思想需要学习

private HashMap<Integer,Book> cache = new HashMap<>();@Override
public Book getBookById(Integer id){Book book = cache.get(id);if(book == null){book = bookDao.selectById(id);cache.put(id,book);}return book;
}

此时调用之前的接口,除了第一次需要查数据库,后面直到服务重启,变量被回收,都不用再去查数据库。同理,写个手机验证码的demo代码:

在这里插入图片描述

看下效果:

在这里插入图片描述
在这里插入图片描述

3、SpringBoot提供缓存的使用

首先导入缓存技术对应的starter:

<dependency>    <groupId>org.springframework.boot</groupId>    <artifactId>spring-boot-starter-cache</artifactId>
</dependency>

配置配或者直接启动类上加@EnableCaching启动缓存

@SpringBootApplication@EnableCaching  //!!!!public class SpringbootApplication {    public static void main(String[] args) {SpringApplication.run(SpringbootApplication.class, args);    }
}

此时,上面用HashMap模拟缓存的Service码就可改为:

@Cacheable(value="cacheSpace",key="#id")public Book getById(Integer id) {    return bookDao.selectById(id);}

即先从cacheSpace这块缓存空间查看,有则返回,没有再查持久层。@Cacheable注解,即以属性里的key值为键,以方法的返回值为value,既存又取,有则取,无则查后存。 以上是背后使用的缓存技术是SpringBoot默认的Simple。SpringBoot提供的缓存技术除了提供默认的缓存方案外,还可以对其他缓存技术进行整合,统一接口,方便缓存技术的开发与管理:

  • Generic
  • JCache
  • Ehcache
  • Hazelcast
  • Infinispan
  • Couchbase
  • Redis
  • Caffeine
  • Simple(默认)
  • memcached

4、手机验证码案例完善

引入@Cacheable注解后,重写并完善下这个验证码的案例。先写个工具类来生成验证码,这个工具类写的不优雅,重点备份下补0串的这种思想吧:

public class CodeUtil {private static final String[] patch = {"000000","00000","0000","000","00","0",""};public static String generatorCode(String tel){int hash = tel.hashCode();int encryption = 20230927;  //加密常量码long result = hash ^ encryption;  //第一次加密,此时,我加密码写死,同一个电话号码的验证码会一直不变long nowTime = System.currentTimeMillis();result = result ^ nowTime;  //引入时间,二次加密long code = Math.abs(result % 1000000);  //取后六位String codeStr = code + "";  //也可能不够6位,比如000147,则上面的long code就是147return patch[codeStr.length()] + codeStr;  //加一个补0数组,根据字符串长度来取对应的补0串,最多补5个0,最少不补,这里为了适配数组下标从0开始,给array[0]给个值}
}

注意根据字符串长度来取数组中对应的补0串时,长度为6,则取array[6],但数组下标从0开始,会越界:

在这里插入图片描述

此时有两种思路处理,一种是上面的,给数组加个下标为0的值,此时str.length()就和数组下标对应上了,也可以直接让str.length()-1:

return patch[codeStr.length() -1 ] + codeStr;

Service层,生成验证码,并存缓存,不能用@Cacheable,它既存又取,这样验证码在缓存失效前都一样,可改为@CachePut只存不取

@Service
@Slf4j
public class MsgServiceImpl implements MsgService {@Resource@Lazy  //解决下循环以来的问题MsgService msgService;/*** 返回验证码* @param tel* @return*/@Override//@Cacheable(value = "telCode",key = "#tel")@CachePut(value = "telCode",key = "#tel")public String getCheckCode(String tel) {String checkCode = CodeUtil.generatorCode(tel);return checkCode;}/*** 校验验证码* @param tel* @param checkCode* @return*/@Overridepublic boolean verify(String tel, String checkCode) {return checkCode.equals(msgService.getCode(tel));}@Override@Cacheable(value = "telCode",key = "#tel")public String getCode(String tel){return null;}
}

关于校验方法里的取验证码,之前写需求用redis,直接redisTemplate.get了,但这里底层缓存技术是Simple,可单独写个方法,上面加@Caceable注解,然后校验方法里调用这个获取缓存值的方法即可实现(此时会有@Cacheable注解失效问题,注意出去绕一圈拿代理对象来调用)。还是利用了@Cacheable注解的特点,先查有无这个key,有就把value当作这个方法的返回值,没有再执行代码方法体。

@Cacheable(value = "telCode",key = "#tel")
public String getCode(String tel){return null;
}

Controller层随便写就行:

@RestController
@RequestMapping("/msg")
public class MsgController {@ResourceMsgService msgService;@GetMapping("{tel}")public String getCode(@PathVariable String tel){return msgService.getCheckCode(tel);}@PostMappingpublic Boolean verifyCode(@RequestParam String tel,String code){return msgService.verify(tel,code);}
}

重点关注:

  • 工具类中加密使用了一个补0数组的思想
  • @Cacheable既存又取,这样验证码在缓存失效前都一样,可改为@CachePut只存不取
  • @Cacheable注解因方法内部调用而失效的解决
  • 不用Redis,再取数据时,引入了一个方法,加@Cacheable注解并返回null,即查到这个key的值就返回,否则返回方法的返回值,即null

相关文章:

【开发篇】十、Spring缓存:手机验证码的生成与校验

文章目录 1、缓存2、用HashMap模拟自定义缓存3、SpringBoot提供缓存的使用4、手机验证码案例完善 1、缓存 缓存是一种介于数据永久存储介质与数据应用之间的数据临时存储介质使用缓存可以有效的减少低速数据读取过程的次数&#xff08;例如磁盘IO&#xff09;&#xff0c;提高…...

【Aurora 8B/10B IP(1)--初步了解】

Aurora 8B/10B IP(1)–初步了解 1 Aurora 8b/10b IP的基本状态: •通用数据通道吞吐量范围从480 Mb/s到84.48 Gb/s •支持多达16个连续粘合7GTX/GTH系列、UltraScale™ GTH或UltraScale+™ GTH收发器和4绑定GTP收发器 •Aurora 8B/10B协议规范v2.3顺从的 •资源成本低(请参…...

C++ vector容器的介绍与使用

一、vector简介 std::vector 是 C 标准模板库 (STL) 中的一个动态数组容器。允许存储元素&#xff08;可以使用任何数据类型作为其元素类型&#xff09;集合&#xff0c;并能够动态调整其大小。 特点&#xff1a; 动态大小&#xff1a;与常规数组不同&#xff0c;vector 可以…...

openstack的组成

OpenStack 是一个开源的云计算平台&#xff0c;由一系列组件构成&#xff0c;各组件之间相互协作&#xff0c;提供了完整的基础设施即服务&#xff08;IaaS&#xff09;解决方案。下面详细解释了 OpenStack 的主要组件及其相互关系&#xff1a; Nova&#xff08;计算服务&…...

[React] React高阶组件(HOC)

文章目录 1.Hoc介绍2.几种包装强化组件的方式2.1 mixin模式2.2 extends继承模式2.3 HOC模式2.4 自定义hooks模式 3.高阶组件产生初衷4.高阶组件使用和编写结构4.1 装饰器模式和函数包裹模式4.2 嵌套HOC 5.两种不同的高阶组件5.1 正向的属性代理5.2 反向的继承 6.如何编写高阶组…...

【逐步剖C++】-第二章-C++类和对象(中)

前言&#xff1a;本章继【逐步剖C】-第二章-C类和对象&#xff08;上&#xff09;介绍有关类和对象更深层次的知识点&#xff0c;这里是文章导图&#xff1a; 本文较长&#xff0c;内容较多&#xff0c;大家可以根据需求跳转到自己感兴趣的部分&#xff0c;希望能对读者有一些帮…...

PL/SQL动态SQL

目录 1. 动态 sql 2. 带参数的动态 sql -- 不使用 USING 传参 1. 动态 sql -- 在 PL/SQL 程序开发中,可以使用 DML 语句,但是很多语句(如 DDL),不能直接在 PL/SQL中执行,这些语句可以使用动态 sql 来实现. 语法格式: EXECUTE IMMEDIATE --动态语句的字符串 [into 变量…...

Python绘图系统24:添加辅助坐标轴

文章目录 辅助坐标增减坐标轴时间轴**代码优化源代码 Python绘图系统&#xff1a; 前置源码&#xff1a; Python打造动态绘图系统&#x1f4c8;一 三维绘图系统 &#x1f4c8;二 多图绘制系统&#x1f4c8;三 坐 标 轴 定 制&#x1f4c8;四 定制绘图风格 &#x1f4c8;五 数据…...

Java自学网站--十几个网站的分析与评测

原文网址&#xff1a;Java自学网站--十几个网站的分析与评测_IT利刃出鞘的博客-CSDN博客 简介 很多想学Java的人不知道怎样选教程&#xff0c;本文对Java自学网站进行评测。 本文不带主观倾向&#xff0c;只客观分析各个网站的区别。 第1类&#xff1a;大型培训机构(黑马等…...

java接口怎么写

Java接口是一种定义规范的抽象类型&#xff0c;可以包含常量和方法的声明。接口在Java编程中具有重要的作用&#xff0c;可以实现代码的重用和灵活性。本文将详细介绍Java接口的编写方式和使用方法。 一、什么是Java接口 在Java中&#xff0c;接口&#xff08;Interface&…...

第8章 Spring(二)

8.11 Spring 中哪些情况下,不能解决循环依赖问题 难度:★★ 重点:★★ 白话解析 有一下几种情况,循环依赖是不能解决的: 1、原型模式下的循环依赖没办法解决; 假设Girl中依赖了Boy,Boy中依赖了Girl;在实例化Girl的时候要注入Boy,此时没有Boy,因为是原型模式,每次都…...

从0开始python学习-24.selenium 浏览器常见的操作

1. 浏览器的最大化/最小化&#xff1a;maximize_window () / minimize_window() 2. 设置浏览器的宽高&#xff1a;set_window_size() 3. 设置浏览器的位置&#xff1a;set_window_position(0,0) —》左上角为原点 4. 刷新&#xff1a;refresh() 5. 前进&#xff1a;forward() 6…...

Canal实现数据同步

1、Canal实现数据同步 canal可以用来监控数据库数据的变化&#xff0c;从而获得新增数据&#xff0c;或者修改的数据。 1.1 Canal工作原理 原理相对比较简单&#xff1a; 1、canal模拟mysql slave的交互协议&#xff0c;伪装自己为mysql slave&#xff0c;向mysql master发送…...

数据库学习笔记——DDL

数据库学习笔记——DDL 建立EMPLOYEE数据库&#xff1a; CREATE TABLE employee(employee_ID int not null,employee_name varchar(20) not null,street varchar(20) not null,city varchar(20) not null,PRIMARY KEY(employee_ID) );CREATE TABLE company(company_name varc…...

MATLAB算法实战应用案例精讲-【人工智能】边缘计算(附python代码实现)

目录 前言 几个高频面试题目 边缘计算和云计算的关系 云计算(cloud computing) 边缘计算...

精彩回顾 | 迪捷软件亮相2023世界智能网联汽车大会

2023年9月24日&#xff0c;2023世界智能网联汽车大会&#xff08;以下简称大会&#xff09;在北京市圆满落幕。迪捷软件北京参展之行圆满收官。 本次大会由工业和信息化部、公安部、交通运输部、中国科学技术协会、北京市人民政府联合主办&#xff0c;是我国首个经国务院批准的…...

【ShaderLab PBR 嗜血边缘角色_美式朋克风格_“Niohoggr“_角色渲染(第一篇)】

嗜血边缘角色Cyberpunk style Unity 渲染 《嗜血边缘》截取其中的片段如下:资源分析其中Guitar贴图4张模型:人物细节图:人物模型 Inspector面板这里做一个区域区分:Body贴图1_BC贴图1_BC属性:Body贴图2_NBody贴图3_CMBody贴图4_SRMBody贴图4_RGBReflection Probe第一版Sha…...

python经典百题之围圈报数

题目:有n个人围成一圈&#xff0c;顺序排号。从第一个人开始报数&#xff08;从1到3报数&#xff09;&#xff0c;凡报到3的人退出圈子&#xff0c;问最后留下的是原来第几号的那位。 程序分析 思路1&#xff1a;模拟游戏过程 使用一个循环队列模拟游戏过程&#xff0c;每次循…...

Google Earth Engine(GEE)案例——如何去除和过滤Landsat和sentinel等系列影像集合中的空影像(三种方法)

简介 本文的主要解决的问题是如何去除和过滤Landsat和sentinel等系列影像集合中的空影像?这个主要源于一下的问题: “从图像集中删除空图像”是什么意思?您的脚本将图像集合过滤到没有图像的日期,这会产生包含 0 个图像的图像集合:https: https://code.earthengine.goog…...

Leetcode 69.x的平方根

给你一个非负整数 x &#xff0c;计算并返回 x 的 算术平方根 。 由于返回类型是整数&#xff0c;结果只保留 整数部分 &#xff0c;小数部分将被 舍去 。 注意&#xff1a;不允许使用任何内置指数函数和算符&#xff0c;例如 pow(x, 0.5) 或者 x ** 0.5 。 示例 1&#xff1…...

51c自动驾驶~合集58

我自己的原文哦~ https://blog.51cto.com/whaosoft/13967107 #CCA-Attention 全局池化局部保留&#xff0c;CCA-Attention为LLM长文本建模带来突破性进展 琶洲实验室、华南理工大学联合推出关键上下文感知注意力机制&#xff08;CCA-Attention&#xff09;&#xff0c;…...

golang循环变量捕获问题​​

在 Go 语言中&#xff0c;当在循环中启动协程&#xff08;goroutine&#xff09;时&#xff0c;如果在协程闭包中直接引用循环变量&#xff0c;可能会遇到一个常见的陷阱 - ​​循环变量捕获问题​​。让我详细解释一下&#xff1a; 问题背景 看这个代码片段&#xff1a; fo…...

安宝特方案丨XRSOP人员作业标准化管理平台:AR智慧点检验收套件

在选煤厂、化工厂、钢铁厂等过程生产型企业&#xff0c;其生产设备的运行效率和非计划停机对工业制造效益有较大影响。 随着企业自动化和智能化建设的推进&#xff0c;需提前预防假检、错检、漏检&#xff0c;推动智慧生产运维系统数据的流动和现场赋能应用。同时&#xff0c;…...

ElasticSearch搜索引擎之倒排索引及其底层算法

文章目录 一、搜索引擎1、什么是搜索引擎?2、搜索引擎的分类3、常用的搜索引擎4、搜索引擎的特点二、倒排索引1、简介2、为什么倒排索引不用B+树1.创建时间长,文件大。2.其次,树深,IO次数可怕。3.索引可能会失效。4.精准度差。三. 倒排索引四、算法1、Term Index的算法2、 …...

Linux-07 ubuntu 的 chrome 启动不了

文章目录 问题原因解决步骤一、卸载旧版chrome二、重新安装chorme三、启动不了&#xff0c;报错如下四、启动不了&#xff0c;解决如下 总结 问题原因 在应用中可以看到chrome&#xff0c;但是打不开(说明&#xff1a;原来的ubuntu系统出问题了&#xff0c;这个是备用的硬盘&a…...

全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比

目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec&#xff1f; IPsec VPN 5.1 IPsec传输模式&#xff08;Transport Mode&#xff09; 5.2 IPsec隧道模式&#xff08;Tunne…...

嵌入式学习笔记DAY33(网络编程——TCP)

一、网络架构 C/S &#xff08;client/server 客户端/服务器&#xff09;&#xff1a;由客户端和服务器端两个部分组成。客户端通常是用户使用的应用程序&#xff0c;负责提供用户界面和交互逻辑 &#xff0c;接收用户输入&#xff0c;向服务器发送请求&#xff0c;并展示服务…...

在 Spring Boot 中使用 JSP

jsp&#xff1f; 好多年没用了。重新整一下 还费了点时间&#xff0c;记录一下。 项目结构&#xff1a; pom: <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://ww…...

水泥厂自动化升级利器:Devicenet转Modbus rtu协议转换网关

在水泥厂的生产流程中&#xff0c;工业自动化网关起着至关重要的作用&#xff0c;尤其是JH-DVN-RTU疆鸿智能Devicenet转Modbus rtu协议转换网关&#xff0c;为水泥厂实现高效生产与精准控制提供了有力支持。 水泥厂设备众多&#xff0c;其中不少设备采用Devicenet协议。Devicen…...

结构化文件管理实战:实现目录自动创建与归类

手动操作容易因疲劳或疏忽导致命名错误、路径混乱等问题&#xff0c;进而引发后续程序异常。使用工具进行标准化操作&#xff0c;能有效降低出错概率。 需要快速整理大量文件的技术用户而言&#xff0c;这款工具提供了一种轻便高效的解决方案。程序体积仅有 156KB&#xff0c;…...