rabbitmq 短信验证码

1**.生成的验证码用redis存 减少数据库压力**

2.通知运营商发送短信的事情交给rabbitmq的队列去做,无论成功或者是失败,用户那边都不知道。没有收到验证码(监听失败)用户只会觉得是运营商的问题,而不会怀疑是我们的系统有问题。

(ps:如果没有用rabbitmq来监听,通知运营商的业务失败了,用户就直接知道系统爆了,然而发送验证码这个业务失败又能怎么样呢?多发几次能成功就行,但是不能让用户知道我们的系统很垃圾,这就是使用mq实现异步调用的原因)


新建一个springboot项目,引入web,redis,rabbitmq

# 应用服务 WEB 访问端口
server.port=8080

# redis配置
spring.data.redis.host=192.168.168.168
spring.data.redis.port=6379
# spring.data.redis.password=123456
spring.data.redis.database=0
# lettuce连接池
# 最大活跃连接数
spring.data.redis.lettuce.pool.max-active=8
# 最大空闲连接数
spring.data.redis.lettuce.pool.max-idle=8
# 最小空闲连接数
spring.data.redis.lettuce.pool.min-idle=0
# 当所有连接都忙时,客户端等待可用连接的最大时间
spring.data.redis.lettuce.pool.max-wait=100ms


# rabbitmq配置
# 主机ip
spring.rabbitmq.host=192.168.168.168
# rabbitmq的编程端口,默认5672
spring.rabbitmq.port=5672
# 账号和密码
spring.rabbitmq.username=chen
spring.rabbitmq.password=123456
# 虚拟主机
spring.rabbitmq.virtual-host=/test
# 通过设置prefetch来控制消费者预取的消息数量。这条配置告诉RabbitMQ的消费者一次只从队列中拉取一条消息进行处理。
spring.rabbitmq.listener.simple.prefetch=1

package com.gmgx.demorabbitmqsms.controller;

import ch.qos.logback.core.util.TimeUtil;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Random;
import java.util.concurrent.TimeUnit;

@Tag(name = "验证码控制器")
@RequestMapping("sms")
@RestController
public class SmsController {
    @Resource
    private RabbitTemplate rabbitTemplate;

    @Resource
    private StringRedisTemplate stringRedisTemplate;


    @Operation(summary = "发送短信验证码")
    @GetMapping("send")
    public String send() {
        //生成4位的数字验证码
        Random rand = new Random();
        String code = (rand.nextInt(8999) + 1000) + "";

        //验证码存在redis,设置1分钟过期  校验时查redis
        stringRedisTemplate.opsForValue().set("smsCode", code, 60, TimeUnit.SECONDS);

        //发送消息到rabbitmq的sms.exchange  这个队列的任务是通知运营商发送短信给用户(模拟)
        rabbitTemplate.convertAndSend("sms.exchange", "", code);
        return "发送成功";//无论怎样都返回发送成功,欺骗用户
    }

    @Operation(summary = "验证")
    @GetMapping("valify/{code}")
    public String valify(@PathVariable String code) {
        if (!stringRedisTemplate.hasKey("smsCode")) {
            return "验证失败";
        }
        if (!code.equals(stringRedisTemplate.opsForValue().get("smsCode"))) {
            return "验证失败";
        }
        stringRedisTemplate.delete("smsCode");
        return "验证成功";
    }
}

package com.gmgx.demorabbitmqsms.listener;


import org.springframework.amqp.core.ExchangeTypes;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

@Component
public class SmsListener {
    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(name = "sms.queue"),
            exchange = @Exchange(name = "sms.exchange", type = ExchangeTypes.DIRECT)
    ))
    public void listen(String msg) {
        try {
            //休眠5秒,模拟通知运营商发送短信给用户
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("【中国移动】 您的验证码为" + msg + " 请在1分钟内校验");
    }
}

测试

相关推荐
开心工作室_kaic14 分钟前
ssm161基于web的资源共享平台的共享与开发+jsp(论文+源码)_kaic
java·开发语言·前端
懒洋洋大魔王15 分钟前
RocketMQ的使⽤
java·rocketmq·java-rocketmq
武子康20 分钟前
Java-06 深入浅出 MyBatis - 一对一模型 SqlMapConfig 与 Mapper 详细讲解测试
java·开发语言·数据仓库·sql·mybatis·springboot·springcloud
转世成为计算机大神1 小时前
易考八股文之Java中的设计模式?
java·开发语言·设计模式
qq_327342731 小时前
Java实现离线身份证号码OCR识别
java·开发语言
阿龟在奔跑2 小时前
引用类型的局部变量线程安全问题分析——以多线程对方法局部变量List类型对象实例的add、remove操作为例
java·jvm·安全·list
飞滕人生TYF2 小时前
m个数 生成n个数的所有组合 详解
java·递归
代码小鑫3 小时前
A043-基于Spring Boot的秒杀系统设计与实现
java·开发语言·数据库·spring boot·后端·spring·毕业设计
真心喜欢你吖3 小时前
SpringBoot与MongoDB深度整合及应用案例
java·spring boot·后端·mongodb·spring
激流丶3 小时前
【Kafka 实战】Kafka 如何保证消息的顺序性?
java·后端·kafka