MQ+短信发送(前端vue)+redis

文章目录


前言

一、发送验证码的使用

短信发送是电信运营商提供的服务,需要访问对应的接口,不同运营商提供的接口地址肯定不一样,如果直接访问这些接口就需要判断收信息的手机号属于哪个运营商,关键在于这些接口不对个人开放,还要考虑调用短信服务的费用问题
因此目前调用短信业务都是使用第三方企业的短信服务,他们与运营商合作,封装了短信接口,调用方法,而且费用相对便宜
MQ+短信发送(前端vue)+redis

短信服务(推荐)

注册购买

第一步:云市场搜索短信服务
点击购买,有5条免费使用,测试也会消耗使用次数,用完了在付费购买即可
MQ+短信发送(前端vue)+redis
找到自己购买的云服务
MQ+短信发送(前端vue)+redis
可以看到已购买的服务

这里有几项重要信息:AppKey AppSecret AppCode 调用购买的这个短信服务接口时候需要用到,用于确认使用者身份

接口 : 调用该服务时访问的接口
MQ+短信发送(前端vue)+redis
参考API,编写发送短信工具类

import cn.hutool.http.Header;
import cn.hutool.http.HttpRequest;

import java.util.HashMap;
import java.util.Map;

/**
 * 测试短信
 */
public class SmsUtilTest {

    public static void main(String[] args) {
        //手机号码
        String mobile = "";
        //验证码
        String code = "";
        //签名ID。(联系客服申请。测试请用:2e65b1bb3d054466b82f0c9d125465e2)
        String smsSignId="";
        //模板ID。(联系客服申请。测试ID请用:908e94ccf08b4476ba6c876d13f084ad,短信内容为 { 验证码:**code**,**minute**分钟内有效,请勿泄漏于他人!})
        String templateId="";
        //应用code  https://market.console.aliyun.com/imageconsole/index.htm?#/bizlist?_k=r5f9m0 查找
        String appCode="";

        //请求连接
        String host = "https://gyytz.market.alicloudapi.com/sms/smsSend";
        //拼装请求体
        Map<String, Object> querys = new HashMap<String, Object>();
        querys.put("mobile", mobile);
        querys.put("param", "**code**:"+code+",**minute**:5");
        querys.put("smsSignId", smsSignId);
        querys.put("templateId", templateId);

        try {
            String result = HttpRequest.post(host)
                    .header(Header.AUTHORIZATION, "APPCODE " + appCode)//头信息,多个头信息多次调用此方法即可
                    .form(querys)//表单内容
                    .timeout(20000)//超时,毫秒
                    .execute().body();
            System.out.println(result);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

二、实例

前端Vue

<template>
<div style="text-align:left">
	用户名:<input type="text" class="txt" v-model="user.username" name="username" />3-20位字符,可由中文、字母、数字和下划线组成<br>
	密码  :<input type="password" class="txt" name="password" v-model="user.password"/>6-20位字符,可使用字母、数字和符号的组合,不建议使用纯数字、纯字母、纯符号<br>
	确认密码:<input type="password" class="txt" name="password" v-model="user.repassword"/><br>
	手机号码:<input type="text" class="txt" name="mobile" v-model="user.mobile" />
    <button  @click.prevent="sendSMS" :disabled="smsBtnDisabled">点击发送短信验证码<span v-if="smsBtnDisabled">{{second}}秒</span></button>
    <br>
	验证码:<input type="text"  name="user.code" v-model="user.code"/><br>
	<input type="submit" value="注册" @click="regist()"/>
</div>
</template>

<script>
export default {
    data() {
        return {
            user:{},
            smsBtnDisabled:false,// true 禁用按钮 false不禁用
            second:5,//倒计时秒数
            timer:null//倒计时对象
        }
    },
    methods: {
        async sendSMS(){
            let res = await this.$http.get("http://localhost:10010/user/sendSms?phone="+this.user.mobile)
            // let res = await this.$http.get("/user/sendSms",{params:user.mobile})
            if(res.data.code==0){
                //发送成功
                alert("发送成功")
                //按钮禁用
                this.smsBtnDisabled = true
                //倒计时:每个1s执行某个函数
                this.timer = setInterval(this.daojishi,1000)
            }
        },
        daojishi(){
            //如果second大于0,那second--
            //否则停止倒计时,按钮生效
            if(this.second>0){
                this.second--
            }else{
                //停止倒计时
                clearInterval(this.timer)
                //恢复秒数。给下次使用
                this.second=5
                //按钮恢复
                this.smsBtnDisabled = false
            }
        },
        async regist(){
          try { 
               let res = await this.$http.post("http://localhost:10010/user/reg",this.user)
            if(res.data.code==0){
                alert("注册成功")
                console.log(res)
                this.$router.push("登录页")
            }else{
                alert("注册失败")
            }
            }catch (error) {
                alert("res.msg")
            }
        }
    },
}
</script>

后端
启动类
UserController

@RestController
@RequestMapping("/user")
public class UserController {

//    @Autowired
//    private HttpServletRequest request;
    @Autowired
    private RabbitTemplate rabbitTemplate;
//    RabbitTemplate  rabbitTemplate;
    @Autowired
    private StringRedisTemplate redisTemplate;

    @PostMapping
    public BaseResult addUser(@RequestBody User user,
                              @RequestHeader("Authorization") String authorization){
//      String token = request.getHeader("authorization");
        Claims claims = JWTUtil.parseToken(authorization, "user");
        Object userId = claims.get("userId");
        System.out.println("新增的用户信息:"+user);

        return BaseResult.success(null);
    }
    /**
     * 1 产生随机码6位
     * 2 保存到rabbitMQ中
     * 3 保存到redis中
     * 4 返回发送成功
     * @param phone
     * @return
     */
    //

    @GetMapping("/sendSms")
    public BaseResult sendSMS(String phone){

//       1 产生随机码6位
        String code = RandomUtil.code();
        //拼接消息内容
        String msg = phone + "%%%%%%" + code;

//       2 保存到rabbitMQ中
        rabbitTemplate.convertAndSend("sms.queue",msg);

//       3 保存到redis中
        redisTemplate.opsForValue().set(phone,code,1, TimeUnit.MINUTES);
//       4 返回发送成功
        return BaseResult.success("成功");

    }


    @PostMapping("/reg")
    public BaseResult reg(@RequestBody User user){
        String s2 = user.getMobile();
        String s = redisTemplate.opsForValue().get(s2);
        System.out.println(s);
        if (s==null){
            return BaseResult.fail();
        }
        if (user.getCode().equals(s)){
            System.out.println("注册成功,"+user);
            redisTemplate.delete(user.getMobile());
            return BaseResult.success("成功"+user);
        }
        return BaseResult.fail();
    }
}

配置文件bootstrap.yaml

spring:
  datasource:
    url: jdbc:mysql://localhost/数据库表名?useSSL=false
    username: 账户名
    password: 密码
    driver-class-name: com.mysql.jdbc.Driver
  application:
  //服务名
    name: userservice
  profiles:
    active: dev
  cloud:
    nacos:
      server-addr: localhost:8848
      config:
        file-extension: yaml
#  rabbitmq:
#    host:# 主机名
#    port: 5672 # 端口
#    virtual-host: / # 虚拟主机
#    username: # 用户名
#    password: # 密码
  redis:
    host: localhost
    port: 6379
    database: 0
    jedis:
      pool:
        max-idle: 8
        min-idle: 0
        max-active: 8
server:
  port: 8000

SmsListener同步redis中的值

@Component
public class SmsListener {

    @RabbitListener(queues = "sms.queue")
    public void listenerWorkQueue1(String msg) throws Exception{

        String[] vals = msg.split("%%%%%%");
        //这里调用短信接口
        AliyunSendSmsUtil.send(vals[0],vals[1]);
        
        System.out.println("sms接收到的消息:【"+msg+"】发送成功");
    }
}

短信接口类

public class AliyunSendSmsUtil {

    /**
     *
     * @param to 手机号码
     * @param code 验证码
     */

    public static void send(String to, String code) {

        String accessKeyId="";
        String accessSecret = "";

        DefaultProfile profile = DefaultProfile.getProfile("cn-hangzhou", accessKeyId, accessSecret);
        IAcsClient client = new DefaultAcsClient(profile);

        CommonRequest request = new CommonRequest();
        request.setSysMethod(MethodType.POST);
        request.setSysDomain("dysmsapi.aliyuncs.com");
        request.setSysVersion("2017-05-25");
        request.setSysAction("SendSms");
        request.putQueryParameter("RegionId", "cn-hangzhou");
        request.putQueryParameter("PhoneNumbers", to);
        request.putQueryParameter("SignName", "");
        request.putQueryParameter("TemplateCode", "SMS_85550034");
        request.putQueryParameter("TemplateParam", "{\"code\":\""+code+"\"}");
        try {
            CommonResponse response = client.getCommonResponse(request);
            System.out.println(response.getData());
        } catch (ServerException e) {
            e.printStackTrace();
        } catch (ClientException e) {
            e.printStackTrace();
        }
        }
        }

启动类

@SpringBootApplication
public class SmsConsumerApplication {


    @Bean
    public Queue createSmsQueue(){
        return new Queue("sms.queue");
    }
    
    public static void main(String[] args) {
        SpringApplication.run(SmsConsumerApplication.class, args);
    }

}

配置文件application.yml

server:
port: 20000
spring:
rabbitmq:
host: # 主机名
port: 5672 # 端口
virtual-host: / # 虚拟主机
username: # 用户名
password: # 密码

2.项目结构及pom

MQ+短信发送(前端vue)+redis

    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
    </dependency>
    <dependency>
        <groupId>org.example</groupId>
        <artifactId>jwt-common03</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
    </dependency>
    <!--nacos配置管理依赖-->
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
    </dependency>
    <!--AMQP依赖,包含RabbitMQ-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-amqp</artifactId>
    </dependency>

    <dependency>
        <groupId>redis.clients</groupId>
        <artifactId>jedis</artifactId>
        <version>2.9.0</version>
    </dependency>

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

</dependencies>
上一篇:springboot 报错 sprintgboot Unknown column '字段名' in 'field list'


下一篇:RabbitMQ部署指南