当前位置: 首页 > 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…...

在rocky linux 9.5上在线安装 docker

前面是指南&#xff0c;后面是日志 sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo sudo dnf install docker-ce docker-ce-cli containerd.io -y docker version sudo systemctl start docker sudo systemctl status docker …...

python/java环境配置

环境变量放一起 python&#xff1a; 1.首先下载Python Python下载地址&#xff1a;Download Python | Python.org downloads ---windows -- 64 2.安装Python 下面两个&#xff0c;然后自定义&#xff0c;全选 可以把前4个选上 3.环境配置 1&#xff09;搜高级系统设置 2…...

UE5 学习系列(三)创建和移动物体

这篇博客是该系列的第三篇&#xff0c;是在之前两篇博客的基础上展开&#xff0c;主要介绍如何在操作界面中创建和拖动物体&#xff0c;这篇博客跟随的视频链接如下&#xff1a; B 站视频&#xff1a;s03-创建和移动物体 如果你不打算开之前的博客并且对UE5 比较熟的话按照以…...

跨链模式:多链互操作架构与性能扩展方案

跨链模式&#xff1a;多链互操作架构与性能扩展方案 ——构建下一代区块链互联网的技术基石 一、跨链架构的核心范式演进 1. 分层协议栈&#xff1a;模块化解耦设计 现代跨链系统采用分层协议栈实现灵活扩展&#xff08;H2Cross架构&#xff09;&#xff1a; 适配层&#xf…...

拉力测试cuda pytorch 把 4070显卡拉满

import torch import timedef stress_test_gpu(matrix_size16384, duration300):"""对GPU进行压力测试&#xff0c;通过持续的矩阵乘法来最大化GPU利用率参数:matrix_size: 矩阵维度大小&#xff0c;增大可提高计算复杂度duration: 测试持续时间&#xff08;秒&…...

蓝桥杯 冶炼金属

原题目链接 &#x1f527; 冶炼金属转换率推测题解 &#x1f4dc; 原题描述 小蓝有一个神奇的炉子用于将普通金属 O O O 冶炼成为一种特殊金属 X X X。这个炉子有一个属性叫转换率 V V V&#xff0c;是一个正整数&#xff0c;表示每 V V V 个普通金属 O O O 可以冶炼出 …...

MySQL的pymysql操作

本章是MySQL的最后一章&#xff0c;MySQL到此完结&#xff0c;下一站Hadoop&#xff01;&#xff01;&#xff01; 这章很简单&#xff0c;完整代码在最后&#xff0c;详细讲解之前python课程里面也有&#xff0c;感兴趣的可以往前找一下 一、查询操作 我们需要打开pycharm …...

AD学习(3)

1 PCB封装元素组成及简单的PCB封装创建 封装的组成部分&#xff1a; &#xff08;1&#xff09;PCB焊盘&#xff1a;表层的铜 &#xff0c;top层的铜 &#xff08;2&#xff09;管脚序号&#xff1a;用来关联原理图中的管脚的序号&#xff0c;原理图的序号需要和PCB封装一一…...

Qt的学习(一)

1.什么是Qt Qt特指用来进行桌面应用开发&#xff08;电脑上写的程序&#xff09;涉及到的一套技术Qt无法开发网页前端&#xff0c;也不能开发移动应用。 客户端开发的重要任务&#xff1a;编写和用户交互的界面。一般来说和用户交互的界面&#xff0c;有两种典型风格&…...

GAN模式奔溃的探讨论文综述(一)

简介 简介:今天带来一篇关于GAN的,对于模式奔溃的一个探讨的一个问题,帮助大家更好的解决训练中遇到的一个难题。 论文题目:An in-depth review and analysis of mode collapse in GAN 期刊:Machine Learning 链接:...