案例 采用Springboot默认的缓存方案Simple在三层架构中完成一个手机验证码生成校验的程序
案例
@Cacheable 是 Spring Framework 提供的一个注解,用于在方法执行前先检查缓存,如果缓存中已存在对应的值,则直接返回缓存中的值,而不执行该方法体。如果缓存中不存在对应的值,则执行方法体,并将方法的返回值存入缓存供下次使用。
在 Spring Boot 中,@Cacheable 注解通常与缓存管理器一起使用,可以轻松地在方法级别上实现缓存功能,避免不必要的重复计算或查询数据库操作,从而提高应用程序的性能和响应速度。
如何使用 @Cacheable 注解:
-
配置缓存管理器:首先,需要在 Spring Boot 应用中配置一个缓存管理器,例如使用 EhCache、Caffeine、Redis 等。这通常可以通过添加相应的依赖和配置来实现。
-
在方法上添加
@Cacheable注解:将@Cacheable注解添加到需要缓存的方法上,并指定缓存的名称或缓存管理器的名称,以及缓存的 key。
这种方式能够显著提高应用程序的性能,特别是在需要频繁访问相同数据的场景下,通过缓存可以避免重复的耗时操作。
案例-生成验证码

这里有一个词语
Caffenine 要记住
当前默认的缓存方案是Simple
缓存的使用案例——手机验证码

首先我们要封装实体类
在domain包下创建类SMSCode

用lombok进行封装
package com.example.demo.domain;import lombok.Data;@Data
public class SMSCode {private String tele;private String code;
}
在做一个业务层接口
放在service包下
有两个方法
第一个方法是生成验证码
第二个方法是一个校验作用

package com.example.demo.service;import com.example.demo.domain.SMSCode;
import org.apache.ibatis.annotations.Mapper;public interface SMSCodeService {public String sendCodeToSMS(String tele);public boolean checkCode(SMSCode smsCode);
}
做业务层的实现类
即为刚刚的接口书写实现类
package com.example.demo.service.impl;import com.example.demo.domain.SMSCode;
import com.example.demo.service.SMSCodeService;
import org.springframework.stereotype.Service;@Service
public class SMSCodeServiceImpl implements SMSCodeService {@Overridepublic String sendCodeToSMS(String tele) {return null;}@Overridepublic boolean checkCode(SMSCode smsCode) {return false;}
}
接下来书写表现层代码
Controller

package com.example.demo.controller;import com.example.demo.domain.SMSCode;
import com.example.demo.service.SMSCodeService;
import jdk.nashorn.internal.runtime.logging.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
@RequestMapping("/sms")
public class SMSCodeController {@Autowiredprivate SMSCodeService smsCodeService;@GetMappingpublic String getCode(String tele){String code =smsCodeService.sendCodeToSMS(tele);return code;}@PostMappingpublic boolean checkCode(SMSCode smsCode){return smsCodeService.checkCode(smsCode);}}
接下来就是最核心的内容了
我们要在业务层去完善代码

我们是不是需要一个验证码
我们去创建一个工具类
去校验对应的验证码
创建一个工具类

注意的是
生成验证码的时候
要进行补全
package com.example.demo.utils;import org.springframework.stereotype.Component;@Component
public class CodeUtils {public String generator(String tele){int hash=tele.hashCode();int encryption=20206666;long result=hash^encryption;long nowTime=System.currentTimeMillis();result=result^nowTime;long code=result%1000000;code=code<0?-code:code;return String.format("%06d",code);}// //启动注释
// public static void main(String[] args) {
// while(true)
// System.out.println(new CodeUtils().generator("19850593532"));
// }}
当然我们也可以拼接
把0 00 000 0000 00000放到一个数组里面去
然后判断生成验证码的长度 然后直接进行拼接
接下来我们要去补全业务层的实现类
我们把缓存注入 挂到实现类上面去

接下来我们要去检查缓存的依赖是否引入boot工程

看看启动响应类里面有没有打开缓存功能

检查完毕
我们直接给业务层实现类挂一个缓存就行

@Override
@Cacheable(value = "smsCode",key="#tele")
public String sendCodeToSMS(String tele) {String code=codeUtils.generator(tele);return code;
}
启动我们的boot工程
我们打开postman
向服务器发起请求
依靠我们之前在表现层书写的get请求

@GetMapping
public String getCode(String tele){String code =smsCodeService.sendCodeToSMS(tele);return code;
}
获取到了验证码

但是这边有个小问题
我们用同一个手机号发验证码
发起请求无论有多少次
获取到的验证码都是一样的
说明有缓存了
所以我们就思考到了
为什么我们每次靠手机号发送验验证码的时候会进入60秒的冷却等待时间
换个注解
仅仅往里面放缓存

@Override
// @Cacheable(value = "smsCode",key="#tele")@CachePut(value = "smsCode",key="#tele")public String sendCodeToSMS(String tele) {String code=codeUtils.generator(tele);return code;}
这样就能获取到了
手机验证码 每次这个数值 都会变化
案例-校验功能

可以去CSDN学习下<artifactId>qcloudsms</artifactId>这个依赖
用到项目中,可以直接给手机发验证码(腾讯云SMS)
但是我们这边会有一个小问题
运行get的时候才会进行缓存
先执行代码在执行注解
注解根本就没有运行
注解没运行 返回null
注解根本就没加载

并没有执行spring容器管理
我们每次执行的时候都是空指针 返回值都是空
作为ioc容器管理的对象,其中注解生效。但如果不使用对象直接调用当然不生效
加了缓存的注解就相当于会给当前类生成一个代理对象, aop的思想, 在controller里调用方法和用this调用方法一个是走代理一个不走代理
同一个类中调用,没有使用ioc容器中的对象调用方法,注解没有被扫描,使用ioc容器的方法,注解才会被扫描
方法调用同实列的方法,代理失效
@Service也是个bean,但是写在service下用this调用,只是走普通方法的调用,没经过spring容器,@Cacheable也就没启动,所以取不到缓存的值,我是这样理解的
我想明白了,上面那个CachePut能使用是因为这个方法是在controller里面被调用的,用bean调用的,而这个是在service里面的方法间调用的,一个普通的类间的方法互相调用
我们的业务层核心逻辑
package com.example.demo.service.impl;import com.example.demo.domain.SMSCode;
import com.example.demo.service.SMSCodeService;
import com.example.demo.utils.CodeUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;@Service
public class SMSCodeServiceImpl implements SMSCodeService {@Autowiredprivate CodeUtils codeUtils;@Override
// @Cacheable(value = "smsCode",key="#tele")@CachePut(value = "smsCode",key="#tele")public String sendCodeToSMS(String tele) {String code=codeUtils.generator(tele);return code;}@Overridepublic boolean checkCode(SMSCode smsCode) {String code=smsCode.getCode();String cacheCode=codeUtils.get(smsCode.getTele());return code.equals(cacheCode);}}
解决方案
我们要把get方法放到工具类里面去

package com.example.demo.utils;import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Component;@Component
public class CodeUtils {public String generator(String tele){int hash=tele.hashCode();int encryption=20206666;long result=hash^encryption;long nowTime=System.currentTimeMillis();result=result^nowTime;long code=result%1000000;code=code<0?-code:code;return String.format("%06d",code);}@Cacheable(value = "smsCode",key="#tele")public String get(String tele){return null;}
}
这样我们就能用bean去调用
这个方法
就能让cacheCode
很巧合的加载进来
我们用postman获取

这样就代表我们的案例书写成功
个人号推广
博客主页
多多!-CSDN博客
Web后端开发
https://blog.csdn.net/qq_30500575/category_12624592.html?spm=1001.2014.3001.5482
Web前端开发
https://blog.csdn.net/qq_30500575/category_12642989.html?spm=1001.2014.3001.5482
数据库开发
https://blog.csdn.net/qq_30500575/category_12651993.html?spm=1001.2014.3001.5482
项目实战
https://blog.csdn.net/qq_30500575/category_12699801.html?spm=1001.2014.3001.5482
算法与数据结构
https://blog.csdn.net/qq_30500575/category_12630954.html?spm=1001.2014.3001.5482
计算机基础
https://blog.csdn.net/qq_30500575/category_12701605.html?spm=1001.2014.3001.5482
回忆录
https://blog.csdn.net/qq_30500575/category_12620276.html?spm=1001.2014.3001.5482
相关文章:
案例 采用Springboot默认的缓存方案Simple在三层架构中完成一个手机验证码生成校验的程序
案例 Cacheable 是 Spring Framework 提供的一个注解,用于在方法执行前先检查缓存,如果缓存中已存在对应的值,则直接返回缓存中的值,而不执行该方法体。如果缓存中不存在对应的值,则执行方法体,并将方法的…...
第四届人工智能、机器人和通信国际会议(ICAIRC 2024)
第四届人工智能、机器人和通信国际会议(ICAIRC 2024) 2024 4th International Conference on Artificial Intelligence, Robotics, and Communication 2024年12月27-29日 | 中国厦门 重要信息 会议官网:www.icairc.net 录用通知时间&…...
ctr/cvr预估之FM模型
ctr/cvr预估之FM模型 在数字化时代,广告和推荐系统的质量直接影响着企业的营销成效和用户体验。点击率(CTR)和转化率(CVR)预估作为这些系统的核心组件,其准确性至关重要。传统的机器学习方法,如…...
HAL-DMA中断空闲接受不定长数据
title: HAL-DMA中断空闲接受不定长数据 tags: STM32HalCubemax 面对无规律长度的数据帧如何处理? 不定长数据接收可以使用每帧数据发送完成后会有一定的空闲时间"帧的时间间隔?" 如果你想每帧都要可以采用dma加空闲中断的方式空闲中断一次就是一帧数据…...
【会议征稿,CPS出版】第四届管理科学和软件工程国际学术会议(ICMSSE 2024,7月19-21)
第四届管理科学和软件工程国际学术会议(ICMSSE 2024)由ACM珠海分会,广州番禺职业技术学院主办;全国区块链行业产教融合共同体,AEIC学术交流中心承办,将于2024年7月19-21日于广州召开。 会议旨在为从事管理与软件工程领域的专家学…...
无引擎游戏开发(3):数据结构设计|功能函数完善
为了简单起见,我们将棋盘的二维数组定义为全局变量。除此之外还要定义一个char类型的全局变量来识别当前的落子类型,我们将其初始化为‘O’。 char Board_data[3][3] {{-, -, -},{-, -, -},{-, -, -}, };char Cur_piece O; 现在回到“读取操作”部分…...
Laravel 高级:了解$loop
Blade 提供 foreach、while、for 和 forelse 等指令来与 PHP 循环配合使用。 您知道吗... 这些指令中有一个方便的 $loop 变量,它指示当前循环迭代?在本文中,我们将探索 $loop 和 loop 指令。😎 使用$loop比foreach更深入 该for…...
深入理解指针(1)
目录: 1. 内存和地址 2. 指针变量和地址 3. 指针变量类型的意义 4. const修饰指针 5. 指针运算 6. 野指针 7. assert断⾔ 8. 指针的使⽤和传址调用 1. 内存和地址 1.1 内存 在讲内存和地址之前,我们想有个⽣活中的案例: 假设有⼀栋宿舍楼&a…...
在无线网中 2.4G、5G、WiFi6、WiFi7 都是什么意思?
有同学问我在无线网中 2.4G/5G/WiFi6/WiFi7 都是什么意思?其实这是两个概念, 2.4G/5G 是频段,WiFi6/WiFi7 是无线协议的版本,千万别把版本和频段搞混了。 WiFi 协议是一系列基于 IEEE 802.11 标准的无线局域网技术协议࿰…...
milvus元数据解析工具milvusmetagui介绍使用
简介 milvusmetagui是一款用来对milvus的元数据进行解析的工具,milvus的元数据存储在etcd上,而且经过了序列化,通过etcd-manager这样的工具来查看是一堆二进制乱码,因此开发了这个工具对value进行反序列化解析。 在这里为了方便交…...
LabVIEW电磁超声热态金属在线缺陷检测系统
LabVIEW软件开发的电磁超声热态金属在线缺陷检测系统针对极端高温环境下的金属材料,进行实时、无损的缺陷检测,具有高精度和高可靠性,能够显著提高材料质量控制的效率和准确性。 项目背景 随着工业技术的发展,高温环境下的金属材…...
leecode代码模板
二分算法: 34. 在排序数组中查找元素的第一个和最后一个位置给你一个按照非递减顺序排列的整数数组 nums,和一个目标值 target。请你找出给定目标值在数组中的开始位置和结束位置。如果数组中不存在目标值 target,返回 [-1, -1]。你必须设计…...
可靠性测试及模型计算
双85高温高湿测试 场景描述: 85℃温度 85%湿度 老化测试 目的: 衡量产品使用寿命 反向推导: 如何根据产品寿命及工况计算双85测试时间 模型介绍 本质是化学反应速率(老化的本质是)随温度的变化 温湿度循环测…...
【Tools】 深入了解Burp Suite:Web应用抓包利器
唱 情 歌 齐齐来一遍 无时无刻都记住掌声 响遍天 来唱 情 歌 由从头再一遍 如情浓有点泪流难避免 音阶起跌拍子改变 每首歌 是每张脸 喜欢我 别遮脸 任由途人发现 🎵 刘德华《十七岁》 在Web应用和移动应用的开发与测试过程中,抓包…...
技术先进、应用广泛、社区活跃的[项目名称]
项目介绍 ---- [项目介绍内容],此项目在开源社区中备受欢迎,其创新性技术和广泛应用领域吸引了大量开发者关注。 代码解释 ---- [代码解释内容],该项目采用[编程语言],通过[技术栈]实现,具有[功能特点]。 …...
Vue中data的属性可以和methods中方法同名吗,为什么?
在Vue中,data的属性不可以和methods中的方法同名,原因如下: 命名规范:从编程规范的角度来看,同名属性或方法可能会导致混淆和难以维护的代码。data通常用于存储组件的状态或数据,而methods则包含组件的行为…...
Esxi上创建windows 11虚拟机
下载windows 11系统镜像 Download Windows 11 (microsoft.com) 虚拟机配置 正常安装部署,需要注意以下几点: 1.cpu开启虚拟化,启用CPU热添加 2.内存开启热插拔 3.磁盘类型最好选择精简置备(磁盘只使用最初所需要的数据存储空间…...
法大大亮相国家级期刊,助力数字政务有实“例”!
近日,在最新发布的国家级学术期刊《市场监督管理》中,法大大作为国内领先的电子签厂商亮相,这也是电子签行业的“第一次”。 截自《市场监督管理》2024年第12期 《市场监督管理》杂志于1953年创刊,是中国工商出版社主办的一本学术…...
【管理咨询宝藏131】麦肯锡波士顿贝恩经典战略咨询报告套装
本报告首发于公号“管理咨询宝藏”,如需阅读完整版报告内容,请查阅公号“管理咨询宝藏”。 【管理咨询宝藏131】麦肯锡波士顿贝恩经典战略咨询报告套装 【格式】PDF版本 【关键词】麦肯锡、波士顿咨询、贝恩咨询、战略咨询、战略落地、战略洞察 【强烈…...
Python | Leetcode Python题解之第160题相交链表
题目: 题解: class Solution:def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode:A, B headA, headBwhile A ! B:A A.next if A else headBB B.next if B else headAreturn A...
观成科技:隐蔽隧道工具Ligolo-ng加密流量分析
1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具,该工具基于TUN接口实现其功能,利用反向TCP/TLS连接建立一条隐蔽的通信信道,支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式,适应复杂网…...
论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(二)
HoST框架核心实现方法详解 - 论文深度解读(第二部分) 《Learning Humanoid Standing-up Control across Diverse Postures》 系列文章: 论文深度解读 + 算法与代码分析(二) 作者机构: 上海AI Lab, 上海交通大学, 香港大学, 浙江大学, 香港中文大学 论文主题: 人形机器人…...
【2025年】解决Burpsuite抓不到https包的问题
环境:windows11 burpsuite:2025.5 在抓取https网站时,burpsuite抓取不到https数据包,只显示: 解决该问题只需如下三个步骤: 1、浏览器中访问 http://burp 2、下载 CA certificate 证书 3、在设置--隐私与安全--…...
在Ubuntu中设置开机自动运行(sudo)指令的指南
在Ubuntu系统中,有时需要在系统启动时自动执行某些命令,特别是需要 sudo权限的指令。为了实现这一功能,可以使用多种方法,包括编写Systemd服务、配置 rc.local文件或使用 cron任务计划。本文将详细介绍这些方法,并提供…...
自然语言处理——Transformer
自然语言处理——Transformer 自注意力机制多头注意力机制Transformer 虽然循环神经网络可以对具有序列特性的数据非常有效,它能挖掘数据中的时序信息以及语义信息,但是它有一个很大的缺陷——很难并行化。 我们可以考虑用CNN来替代RNN,但是…...
Map相关知识
数据结构 二叉树 二叉树,顾名思义,每个节点最多有两个“叉”,也就是两个子节点,分别是左子 节点和右子节点。不过,二叉树并不要求每个节点都有两个子节点,有的节点只 有左子节点,有的节点只有…...
docker 部署发现spring.profiles.active 问题
报错: org.springframework.boot.context.config.InvalidConfigDataPropertyException: Property spring.profiles.active imported from location class path resource [application-test.yml] is invalid in a profile specific resource [origin: class path re…...
【从零学习JVM|第三篇】类的生命周期(高频面试题)
前言: 在Java编程中,类的生命周期是指类从被加载到内存中开始,到被卸载出内存为止的整个过程。了解类的生命周期对于理解Java程序的运行机制以及性能优化非常重要。本文会深入探寻类的生命周期,让读者对此有深刻印象。 目录 …...
破解路内监管盲区:免布线低位视频桩重塑停车管理新标准
城市路内停车管理常因行道树遮挡、高位设备盲区等问题,导致车牌识别率低、逃费率高,传统模式在复杂路段束手无策。免布线低位视频桩凭借超低视角部署与智能算法,正成为破局关键。该设备安装于车位侧方0.5-0.7米高度,直接规避树枝遮…...
图解JavaScript原型:原型链及其分析 | JavaScript图解
忽略该图的细节(如内存地址值没有用二进制) 以下是对该图进一步的理解和总结 1. JS 对象概念的辨析 对象是什么:保存在堆中一块区域,同时在栈中有一块区域保存其在堆中的地址(也就是我们通常说的该变量指向谁&…...
