发表于: 2019-10-11 22:30:33

1 1030


今日完成

完成手机发送验证码

1.前端

1.1页面展示

<%--2.手机验证码登录--%>
<h2>手机快捷登录</h2>
<div id="phone-login">
   <form role="form" id="phone_form" action="${ctx}/doLogin" method="post">

       <%--手机号--%>
       <label for="phone">手机号</label>
       <input type="text" id="phone" name="phone" placeholder="手机号" onblur="checkPhone();">
       <span id="phone_span"></span>
       <br>

       <%--验证码--%>
       <label for="phone_code">验证码</label>
       <input type="text" id="phone_code" name="phone_code" placeholder="验证码" onclick="checkPhoneCode();">
       <button id="go" onclick="getPhoneCode();">获取验证码</button>
       <br>

       <%--注册按钮--%>
       <button type="submit" class="btn btn-default" id="phone_btn" onclick="checkButton();">登录</button>
       <a href = "regist.jsp" >立即注册</a>
   </form>
</div>

1.2绑定函数

1.校验手机号:checkPhone

//1.1校验手机号
var flag2 = false;
function checkPhone(){
var phone = $("#phone").val();
   phone = phone.replace(/^\s+|\s+$/g,"");
   if(!(/^1[3|4|5|8|7|9][0-9]\d{8}$/.test(phone))){
   $("#phone_span").text("手机号码非法,请重新输入!").css("color","red");
       flag2 = false;
   }else{
       $.ajax({
           type:'post',
           url:'/checkPhone',
           data: {"phone":phone},
           dataType:'json',
           success:function(data){
           var val = data['message'];
               if(val=="success"){
          //未注册
                   $("#phone_span").text("该手机号还未注册!");

                   flag2 = false;

               }else{
          //注册
                   $("#phone_span").text("");

                   flag2 = true;
               }
          }
      });

   }
   return flag2;
}

2.手机验证码检查:checkPhoneCode

//1.2手机验证码检查
var p_flag = false;
function checkPhoneCode(){
var reg = /^\d{4}\b/;
   var code = $("#phone_code").val();
   if(reg.test(code)){
       p_flag = true;
   }else {
       p_flag = false;
   }
   return p_flag;
}

3.手机倒计时:countDown

function countDown(s){
if(s <= 0){
       $("#go").text("重新获取");
       $("#go").removeAttr("disabled");
       return;
   }
   /* $("#go").val(s + "秒后重新获取");*/
   $("#go").text(s + "秒后重新获取");
   setTimeout("countDown("+(s-1)+")",1000);
}

4.获取手机验证码:getPhoneCode

function getPhoneCode(){
    if(!flag2){
        $("#phone_span").text("手机号码非法或者未注册!").css("color","red");
    }else {
       //  发送短信给用户手机..
       // 1 发送一个HTTP请求,通知服务器 发送短信给目标用户
             var phone =$("input[name='phone']").val();// 用户输入的手机号
              // 用户输入手机号校验通过
              $("#go").attr("disabled", "disabled");
       countDown(60);
       $.ajax({
           method: 'POST',
           url: '${ctx}/sendSms',// 发送验证码给ActiveQM, 同时保存验证码到redis数据库
                      data : {
           phone : phone
           },
           success:function(data) {
           var tt = data["msg"];
               if(tt){
                   alert("发送短信成功!");
               }else{
                   alert("发送短信出错,请联系管理员");
               }
           }
       });
   }
   return false;
}

5.登录:checkButton

function checkButton() {
if(checkPhone()&& checkPhoneCode()){
    // 校验用户名和密码
       $("#phone_span").text("").css("color","red");
       $("#phone_form").submit();
   }else {
       alert("请输入手机号和6位验证码!");
   }
}


2.后端

2.1环境配置:ActiveMQ

1.applicationContext-activemq.xml:就改个监听器

<!-- 扫瞄包-->
<context:component-scan base-package="com.jnshu.activemq" />
<!-- ActiveMQ 连接工厂 -->
<!-- 真正可以产生ConnectionConnectionFactory,由对应的 JMS服务厂商提供-->
<!-- 如果连接网络:tcp://ip:61616;未连接网络:tcp://localhost:61616 以及用户名,密码-->
<amq:connectionFactory id="amqConnectionFactory" brokerURL="tcp://localhost:61616" userName="admin" password="admin"  />

<!-- Spring Caching连接工厂 -->
<!-- Spring用于管理真正的ConnectionFactoryConnectionFactory -->
<bean id="connectionFactory" class="org.springframework.jms.connection.CachingConnectionFactory">
  <!-- 目标ConnectionFactory对应真实的可以产生JMS ConnectionConnectionFactory -->
  <property name="targetConnectionFactory" ref="amqConnectionFactory"></property>
  <!-- 同上,同理 -->
  <!-- <constructor-arg ref="amqConnectionFactory" /> -->
  <!-- Session缓存数量 -->
  <property name="sessionCacheSize" value="100" />
</bean>

<!-- Spring JmsTemplate 的消息生产者 start-->
<!-- 定义JmsTemplateQueue类型 -->
<bean id="jmsQueueTemplate" class="org.springframework.jms.core.JmsTemplate">
  <!-- 这个connectionFactory对应的是我们定义的Spring提供的那个ConnectionFactory对象 -->
  <constructor-arg ref="connectionFactory" />
  <!-- pub/sub模型(发布/订阅),即队列模式 -->
  <property name="pubSubDomain" value="false" />
</bean>

<!-- Spring JmsTemplate 的消息生产者 end -->

<!-- 消息消费者 start-->
<!-- 定义Queue监听器 -->
<jms:listener-container destination-type="queue" container-type="default" connection-factory="connectionFactory" acknowledge="auto">
  <!-- 默认注册bean名称,应该是类名首字母小写  -->
  <jms:listener destination="login_msg" ref="smsAuthenCode"/>
  <jms:listener destination="email_msg" ref="emailAuthenCode"/>
</jms:listener-container>
<!-- 消息消费者 end -->

2.web.xml

<context-param>
 <param-name>contextConfigLocation</param-name>
 <param-value>
   classpath*:spring-mybatis.xml
   classpath*:applicationContext-redis.xml
   classpath*:applicationContext-activemq.xml
 </param-value>
</context-param>

2.2Controller

1.发送手机验证码

/*3.发送手机验证码*/
@RequestMapping("/sendSms")
@ResponseBody
public Map<String,Object> index(Model model, @RequestParam(value = "phone",required = false) final String phone) {
Map map = new HashMap<String,Object>( );
     try { //  发送验证码操作
              final String code = RandStringUtils.getCode();
       log.info("发送的手机号:"+phone+" 发送的验证码:"+code);
       redisTemplate.opsForValue().set(phone, code, 60, TimeUnit.SECONDS);// 6 0秒 有效 redis保存验证码
              log.info("--------短信验证码为:"+code);
       // 调用ActiveMQ jmsTemplate,发送一条消息给MQ
       jmsTemplate.send("login_msg", new MessageCreator() {
            public Message createMessage(javax.jms.Session session) throws JMSException {
               MapMessage mapMessage = session.createMapMessage();
               mapMessage.setString("phone", phone);
               mapMessage.setString("code", code);
               log.info("Mq进去了???");
               return mapMessage;
           }
      });
   } catch (Exception e) {
     map.put( "msg",false );
   }
     map.put( "msg",true );
     return map;
}

2.3工具类:就改几个地方,其余不变

public class SendMessage {
  private static String accessKeyId = "LTAI4FvNF4k2KFUNZV8F6ih1";//你的accessKeyId,参考本文档步骤2
  private static String accessKeySecret = "IXhk77Y4oHAWk0951Wl79EtUGWYMV2";//你的accessKeySecret,参考本文档步骤2
  private static String setSignName = "技能树验证码";
  private static String dayutemplateCode = "SMS_175240801";

  public static void sendMessages(String code,String phone){
     //设置超时时间-可自行调整
          System.setProperty("sun.net.client.defaultConnectTimeout", "10000");
     System.setProperty("sun.net.client.defaultReadTimeout", "10000");
     //初始化ascClient需要的几个参数
          final String product = "Dysmsapi";//短信API产品名称
          final String domain = "dysmsapi.aliyuncs.com";//短信API产品域名
          //替换成你的AK
     //初始化ascClient,暂时不支持多region
     IClientProfile profile = DefaultProfile.getProfile("cn-hangzhou", accessKeyId,accessKeySecret);
     try {
       DefaultProfile.addEndpoint("cn-hangzhou", "cn-hangzhou", product, domain);
     } catch (ClientException e) {
       e.printStackTrace();
     }
     IAcsClient acsClient = new DefaultAcsClient(profile);
     //组装请求对象
          SendSmsRequest request = new SendSmsRequest();
     //必填:待发送手机号。支持以逗号分隔的形式进行批量调用,批量上限为20个手机号码,批量调用相对于单条调用及时性稍有延迟,验证码类型的短信推荐使用单条调用的方式
          request.setPhoneNumbers(phone);
     //必填:短信签名-可在短信控制台中找到
          request.setSignName(setSignName);
     //必填:短信模板-可在短信控制台中找到
          request.setTemplateCode(dayutemplateCode);
     //可选:模板中的变量替换JSON,如模板内容为"亲爱的${name},您的验证码为${code}",此处的值为
     request.setTemplateParam("{\"code\":\"" + code + "\"}");
     //可选:outId为提供给业务方扩展字段,最终在短信回执消息中将此值带回给调用者
          request.setOutId("yourOutId");
     //请求失败这里会抛ClientException异常
          SendSmsResponse sendSmsResponse = null;
     try {
        sendSmsResponse = acsClient.getAcsResponse(request);
     } catch (ServerException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
     } catch (ClientException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
     }
     if(sendSmsResponse.getCode() != null && sendSmsResponse.getCode().equals("OK")) {
     }
}

2.4调用ActiveMQ

@Component
public class SmsAuthenCode implements MessageListener {
public void onMessage(Message message) {
       MapMessage mapMessage = (MapMessage) message;
       // 调用SMS服务发送短信   SmsSystem阿里大于发送短信给客户手机实现类
       try {
           // 大于发送短信 Map 来自ActiveMQ 生成者
                      SendMessage.sendMessages( mapMessage.getString("code"), mapMessage.getString("phone") );
           System.out.println( "-----发送消息成功..."+mapMessage.getString("code"));
       } catch (Exception e) {//JMS
           e.printStackTrace();
       }
}
}

3.好处

通过监听器名字的不同,可以区分是邮箱发送的验证码还是手机发送的验证码

其实就是一个中转站,区分消息消费者(接受到验证码的人)和消息生产者(我们),在中转站中调用发送短信的工具类,并记录发送的条数、发送的主体等信息。

也可以直接在Controller中调用工具类


碰到问题

碰到好多问题,就是改上面配置,不懂怎么描述配置还是比较固定的东西,最终配置成这样就能跑了


明日计划

IO流的知识,后天完成文件上传


启发


返回列表 返回列表
评论

    分享到