案例 采用Springboot默认的缓存方案Simple在三层架构中完成一个手机验证码生成校验的程序

简介: 案例 采用Springboot默认的缓存方案Simple在三层架构中完成一个手机验证码生成校验的程序

案例

@Cacheable 是 Spring Framework 提供的一个注解,用于在方法执行前先检查缓存,如果缓存中已存在对应的值,则直接返回缓存中的值,而不执行该方法体。如果缓存中不存在对应的值,则执行方法体,并将方法的返回值存入缓存供下次使用。

在 Spring Boot 中,@Cacheable 注解通常与缓存管理器一起使用,可以轻松地在方法级别上实现缓存功能,避免不必要的重复计算或查询数据库操作,从而提高应用程序的性能和响应速度。

如何使用 @Cacheable 注解:

  1. 配置缓存管理器:首先,需要在 Spring Boot 应用中配置一个缓存管理器,例如使用 EhCache、Caffeine、Redis 等。这通常可以通过添加相应的依赖和配置来实现。
  2. 在方法上添加 @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 {
    @Override
    public String sendCodeToSMS(String tele) {
        return null;
    }
 
    @Override
    public 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 {
 
    @Autowired
    private SMSCodeService smsCodeService;
 
    @GetMapping
    public String getCode(String tele){
        String code =smsCodeService.sendCodeToSMS(tele);
        return code;
    }
 
    @PostMapping
    public 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 {
 
    @Autowired
    private 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;
    }
 
    @Override
    public 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获取

这样就代表我们的案例书写成功

目录
相关文章
|
14天前
|
消息中间件 NoSQL Java
springboot整合常用中间件框架案例
该项目是Spring Boot集成整合案例,涵盖多种中间件的使用示例,每个案例项目使用最小依赖,便于直接应用到自己的项目中。包括MyBatis、Redis、MongoDB、MQ、ES等的整合示例。
65 1
|
15天前
|
Web App开发 定位技术 iOS开发
Playwright 是一个强大的工具,用于在各种浏览器上测试应用,并模拟真实设备如手机和平板。通过配置 `playwright.devices`,可以轻松模拟不同设备的用户代理、屏幕尺寸、视口等特性。此外,Playwright 还支持模拟地理位置、区域设置、时区、权限(如通知)和配色方案,使测试更加全面和真实。例如,可以在配置文件中设置全局的区域设置和时区,然后在特定测试中进行覆盖。同时,还可以动态更改地理位置和媒体类型,以适应不同的测试需求。
Playwright 是一个强大的工具,用于在各种浏览器上测试应用,并模拟真实设备如手机和平板。通过配置 `playwright.devices`,可以轻松模拟不同设备的用户代理、屏幕尺寸、视口等特性。此外,Playwright 还支持模拟地理位置、区域设置、时区、权限(如通知)和配色方案,使测试更加全面和真实。例如,可以在配置文件中设置全局的区域设置和时区,然后在特定测试中进行覆盖。同时,还可以动态更改地理位置和媒体类型,以适应不同的测试需求。
17 1
|
1月前
|
前端开发 Java Apache
Springboot整合shiro,带你学会shiro,入门级别教程,由浅入深,完整代码案例,各位项目想加这个模块的人也可以看这个,又或者不会mybatis-plus的也可以看这个
本文详细讲解了如何整合Apache Shiro与Spring Boot项目,包括数据库准备、项目配置、实体类、Mapper、Service、Controller的创建和配置,以及Shiro的配置和使用。
287 1
Springboot整合shiro,带你学会shiro,入门级别教程,由浅入深,完整代码案例,各位项目想加这个模块的人也可以看这个,又或者不会mybatis-plus的也可以看这个
|
1月前
|
Web App开发 JavaScript Java
elasticsearch学习五:springboot整合 rest 操作elasticsearch的 实际案例操作,编写搜索的前后端,爬取京东数据到elasticsearch中。
这篇文章是关于如何使用Spring Boot整合Elasticsearch,并通过REST客户端操作Elasticsearch,实现一个简单的搜索前后端,以及如何爬取京东数据到Elasticsearch的案例教程。
174 0
elasticsearch学习五:springboot整合 rest 操作elasticsearch的 实际案例操作,编写搜索的前后端,爬取京东数据到elasticsearch中。
|
1月前
|
C#
C# 图形验证码实现登录校验代码
C# 图形验证码实现登录校验代码
75 2
|
2月前
|
消息中间件 Java Kafka
springboot项目启动报错-案例情景介绍
springboot项目启动报错-案例情景介绍
61 2
|
2月前
|
前端开发 PHP
ThinkPHP 验证码扩展库的使用,以及多应用模式下,如何自定义验证码校验规则
本文介绍了在ThinkPHP框架中使用验证码扩展库的方法,包括安装验证码扩展库、在页面中使用验证码、自定义验证码配置以及校验验证码的步骤和代码示例。
ThinkPHP 验证码扩展库的使用,以及多应用模式下,如何自定义验证码校验规则
|
3月前
|
SQL 前端开发 NoSQL
SpringBoot+Vue 实现图片验证码功能需求
这篇文章介绍了如何在SpringBoot+Vue项目中实现图片验证码功能,包括后端生成与校验验证码的方法以及前端展示验证码的实现步骤。
SpringBoot+Vue 实现图片验证码功能需求
|
2月前
|
vr&ar 图形学 UED
电子沙盘VR模型大屏平板手机微信使用方案
数字孪生电子沙盘和VR模型被广泛应用在房地产等行业,为不同设备定制不同版本的模型是常见做法。然而,通过实时云渲染技术,可以将PC端的VR模型转化为网页版,使用户能够在平板或手机上流畅浏览详细信息,无需开发多个版本。这不仅提升了用户体验,还简化了模型提供商的工作流程,降低了成本。尤其在新楼盘发布时,可通过公众号或广告链接快速吸引潜在客户。成本主要取决于并发用户数及显卡性能要求,但该技术显著提高了跨设备访问的便利性。
50 1
|
3月前
|
存储 监控 开发工具
Django 后端架构开发:手机与邮箱验证码接入、腾讯云短信SDK和网易邮箱
Django 后端架构开发:手机与邮箱验证码接入、腾讯云短信SDK和网易邮箱
63 0