登录之手机号码快捷登录(ActiveMQ+阿里大于)

准备工作:登录阿里云官网开通短信服务。
https://dysms.console.aliyun.com

QQ截图20200828204050.png

首先需要添加签名管理和模板管理。
签名管理
QQ截图20200828204438.png

模板管理
QQ截图20200828204359.png

这两步操作是需要的审核的。

查看 Access Key ID 和 Access Key Secret。没有就新建

QQ截图20200828205015.png
QQ截图20200828205106.png

发送短信的格式为:【短信签名名称】+ 短信模板内容

ActiveMQ 简介
ActiveMQ 是 Apache 旗下产品,是一款优秀的消息中间件。主要解决应用耦合,异步消息,流量削锋等问题,实现高性能,高可用。

你可以把 ActiveMQ 想象成一个大的容器,首先生产者把消息发送到这个大容器中,然后消费者监听,如果有消息就从这个大容器中消费消息,起到一个缓冲的作用。

下载并运行
去官网下载
http://activemq.apache.org/download.html

QQ截图20200828205614.png

下载完成后进行解压,进入 apache-activemq-5.15.3\bin\win64 目录(32 位系统进入 Win32),然后点击运行 activemq.bat。

可以通过 http://localhost:8161/ 访问 ActiveMQ 消息管理后台页面,如下图所示:

QQ截图20200828205709.png

点击 Manage ActiveMQ broker 进行登录,用户名和密码均为:admin。

登录后可以查看 Queues 消息队列等信息(如果没有发送过短信则为空白),如下图:

QQ截图20200828205829.png

ActiveMQ 相关配置

导入相关依赖:

 <!--activeMQ-->
    <dependency>
      <groupId>org.apache.activemq</groupId>
      <artifactId>activemq-all</artifactId>
      <version>5.2.0</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-jms</artifactId>
      <version>${spring.version}</version>
    </dependency>
 <!-- https://mvnrepository.com/artifact/org.apache.xbean/xbean-spring
activeMQ中会用到,发送短信的配置文件中有用到
     -->
    <dependency>
      <groupId>org.apache.xbean</groupId>
      <artifactId>xbean-spring</artifactId>
      <version>4.0</version>
      <exclusions>
        <exclusion>
          <artifactId>commons-logging</artifactId>
          <groupId>commons-logging</groupId>
        </exclusion>
      </exclusions>
    </dependency>

applicationContext-activemq.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:amq="http://activemq.apache.org/schema/core"
       xmlns:jms="http://www.springframework.org/schema/jms"
       xsi:schemaLocation="
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/jms
        http://www.springframework.org/schema/jms/spring-jms.xsd
        http://activemq.apache.org/schema/core
        http://activemq.apache.org/schema/core/activemq-core.xsd ">

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

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

    <!-- Spring JmsTemplate 的消息生产者 start-->
    <!-- 定义JmsTemplate的Queue类型 -->
    <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-container>

    <!-- 消息消费者 end -->


</beans>

主要是 ActiveMQ 的连接配置以及生产者和消费者的配置。上面注释很详细,这里就不做重复介绍了。
web.xml 引入 applicationContext-activemq.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>
    
```
ActiveMQ 消息监听器的创建(消费者)
配置文件配置完成并引入后,创建消息监听器,监听消息的存在。

在 wang.dreamland.www 包下新建 activemq 包,在 activemq 包下新建消息监听器类 SmsAuthenCode.java:
SmsAuthenCode.java

    ```
package wang.dreamland.www.activemq;

import org.springframework.stereotype.Component;
import javax.jms.MapMessage;
import javax.jms.Message;
import javax.jms.MessageListener;

/**
 * Created by wly on 2018/4/22.
 */
@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("telephone") );
            System.out.println( "-----发送消息成功..."+mapMessage.getString("code"));
        } catch (Exception e) {//JMS
            e.printStackTrace();
        }
    }
}

```
```

代码解读如下:

(1)不知道属于哪一层时使用 @Component 注解,将对象交给 Spring 管理;

(2)消息监听类实现消息监听接口 MessageListener 重写 onMessage 方法;

(3)将消息 message 强制转换为 MapMessage;

(4)从 MapMessage 中取出手机验证码和手机号,调用发送短信的方法将短信发送给用户,下文将对这一部分做解释。

阿里大于发送短信类 SendMessage 的创建
创建过程主要包括以下四步。

1.首先,下载阿里大于 SDK,选择 Java下载。

https://help.aliyun.com/document_detail/55359.html?spm=a2c4g.11186623.2.8.2bNpLw

2.然后,将 aliyun-java-sdk-core-3.3.1.jar 和 aliyun-java-sdk-dysmsapi-1.0.0.jar 打包到本地 Maven 仓库。
打开cmd,输入回车,-Dfile为解压文件路径及jar包名,-DgroupId为文件夹(可以随便取),-DartifacteId为com.lianwei下的包名

mvn install:install-file -Dfile=E:\ActiveMQ\dysms_java\java\api_sdk\aliyun-java-sdk-dysmsapi\aliyun-java-sdk-dysmsapi-1.0.0.jar -DgroupId=com.lianwei -DartifactId=dayu-sdk-dysmsapi -Dversion=1.0.0 -Dpackaging=jar -DgeneratePom=true -DcreateChecksum=true

mvn install:install-file -Dfile=E:\ActiveMQ\dysms_java\java\api_sdk\aliyun-java-sdk-core\aliyun-java-sdk-core-3.3.1.jar -DgroupId=com.lianwei -DartifactId=dayu-sdk-core -Dversion=3.3.1 -Dpackaging=jar -DgeneratePom=true -DcreateChecksum=true

QQ截图20200828211132.png

QQ截图20200828211323.png

QQ截图20200828211304.png

在 pom.xml 中引入刚才打包好的阿里大于依赖:

<!-- 阿里大于依赖  这个包是自己打包出来的 repostitory中有jar包,但是repo中没有jar包-->
    <dependency>
      <groupId>com.lianwei</groupId>
      <artifactId>dayu-sdk-core</artifactId>
      <version>3.3.1</version>
    </dependency>
    <dependency>
      <groupId>com.lianwei</groupId>
      <artifactId>dayu-sdk-dysmsapi</artifactId>
      <version>1.0.0</version>
    </dependency>

groupId 对应上面的 -DgroupId,artifactId 对应上面的 -DartifactId,version 对应上面的 -Dversion
如果这里找不到jar包,可以查看自己的maven库中是否存在jar包

QQ截图20200828211610.png

刚开始我这里也是导不了jar包,结果发现Repository中有jar包,虽然repo中有响应的文件夹,但是确没有jar包,从Repository中复制过去就解决了。

补充下:阿里云这个短信服务可以直接从Maven中引入进来(前面一些操作就当作是练习了)
    <!-- 阿里云短信服务所需 -->
    <dependency>
      <groupId>com.aliyun</groupId>
      <artifactId>aliyun-java-sdk-core</artifactId>
      <version>4.0.6</version> <!-- 注:如提示报错,先升级基础包版,无法解决可联系技术支持 -->
    </dependency>
    <dependency>
      <groupId>com.aliyun</groupId>
      <artifactId>aliyun-java-sdk-dysmsapi</artifactId>
      <version>1.1.0</version>
    </dependency>


在 activemq 包下新建发送短信类 SendMessage.java:

import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsRequest;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.exceptions.ServerException;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.profile.IClientProfile;

public class SendMessage {
    private static String accessKeyId = "你的accessKeyId";//你的accessKeyId,参考本文档步骤2
    private static String accessKeySecret = "你的accessKeySecret";//你的accessKeySecret,参考本文档步骤2
    private static String setSignName = "你的短信签名名称";
    private static String dayutemplateCode = "你的短信模板CODE";

    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}"时,此处的值为
        //"{\"number\":\"" + 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")) {
            //请求成功
        }
    }
}

手机快捷登录流程
手机快捷登录的流程,主要包括下面几步。

1.手机号 input 框离焦事件判断。

判断该手机号是否合法;
如果手机号合法,则判断该手机号是否是已激活用户。
2.获取验证码点击事件。

判断步骤1是否返回 true;
返回 true 则发送获取验证码并同时设置倒计时 60s;
倒计时60s结束才能点击重新获取。
3.验证码 input 框离焦事件。

判断验证码是否为6位纯数字(防止恶意登录),是则返回 true。
4.登录点击事件

判断手机号和验证码均返回 true 时则提交表单。

    //获取验证码
    $(function () {
        var go = document.getElementById('go');

        go.onclick = function (ev){
            if(!flag2){
                $("#phone_span").text("手机号码非法或者未注册!").css("color","red");
            }else {
                //  发送短信给用户手机..
                // 1 发送一个HTTP请求,通知服务器 发送短信给目标用户
                var telephone =$("input[name='telephone']").val();// 用户输入的手机号
                    // 用户输入手机号校验通过
                    $("#go").attr("disabled", "disabled");
                    countDown(60);

                    $.ajax({
                        method: 'POST',
                        url: '${ctx}/sendSms',
                        data : {
                            telephone : telephone
                        },
                        success:function(data) {
                            var tt = data["msg"];
                            if(tt){
                                 alert("发送短信成功!");

                            }else{
                                alert("发送短信出错,请联系管理员");
                            }
                        }
                    });
                }


            var oEvent = ev || event;
            //js阻止链接默认行为,没有停止冒泡
            oEvent.preventDefault();

        }
    });

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




    

代码解读如下:

(1) $(function () {}); 代表页面加载完成函数;

(2)通过 document.getElementById 获取文档对象 DOM,赋值给 go;

(3)给 go 绑定一个 onclick 点击事件函数;

(4)如果检验手机号返回的是 flag2=false,则给予错误提示;

(5)如果检验手机号成功后,通过属性过滤选择器获取 input 框对象,并通过对象的 val() 方法获取手机号;

(6)通过 $("#go").attr("disabled", "disabled") 方法将获取验证码按钮设置成不可点击;

(7)调用 countDown 倒计时方法,如果倒计时到0秒后,按钮显示重新获取,并移除 disabled 属性,按钮可再次点击,如果 0<s<=60 则按钮上显示 s 秒后重新获取,不可点击,每秒 s-1;

(8)发送 AJAX 请求,映射 URL 为 /sendSms,请求参数是手机号;

(9)success 回调函数返回的结果如果是true,则提示发送成功。否则提示发送失败,联系管理员;

(10)oEvent.preventDefault() 阻止链接默认行为。主要是为了返回错误信息时停留在手机快捷登录标签。

@Resource
 private UserService userService;
 @Resource// redis数据库操作模板
 private RedisTemplate<String, String> redisTemplate;// jdbcTemplate HibernateTemplate

 @Resource
 @Qualifier("jmsQueueTemplate")
 private JmsTemplate jmsTemplate;// mq消息模板.
/**
  * 发送手机验证码
  * @param model
  * @param telephone
  * @return
  */
 @RequestMapping("/sendSms")
 @ResponseBody
 public Map<String,Object> index(Model model, @RequestParam(value = "telephone",required = false) final String telephone ) {
     Map map = new HashMap<String,Object>(  );
     try { //  发送验证码操作
         final String code = RandStringUtils.getCode();//获取6位数的验证码
         redisTemplate.opsForValue().set(telephone, code, 120, TimeUnit.SECONDS);// 60秒 有效 redis保存验证码
         log.debug("--------短信验证码为:"+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("telephone",telephone);
                 mapMessage.setString("code", code);
                 return mapMessage;
             }
         });
     } catch (Exception e) {
         map.put( "msg",false );
     }
     map.put( "msg",true );
     return map;

 }

(1)通过 @Autowired 注解注入 UserService、RedisTemplate,通过 @Autowired 和 @Qualifier 结合注入 JmsTemplate,参数是配置文件中配置的队列 ID,主要是为了区分有多个类型的情况,指定注入(这里可以不指定),比如,如果再定义一个订阅模式就需要加 @Qualifier 注解进行指定注入:

<!-- 定义JmsTemplate的Topic类型 -->
      <bean id="jmsTopicTemplate" class="org.springframework.jms.core.JmsTemplate">
       <!-- 这个connectionFactory对应的是我们定义的Spring提供的那个ConnectionFactory对象 -->
          <constructor-arg ref="connectionFactory" />
           <!-- pub/sub模型(发布/订阅) -->
           <property name="pubSubDomain" value="true" />
       </bean>

(2)通过 RandStringUtils 工具类随机生成六位数字验证码,该工具类也放在了文末的百度网盘链接中。

(3)将6位随机验证码保存到 Redis 中,时效为60秒,key=手机号,value=验证码。

(4)调用 ActiveMQ 消息模板对象生产一条消息,发送给 MQ。
RandStringUtils .java

import java.util.Random;

/**
 * Created by wly on 2018/4/22.
 */
public class RandStringUtils {
    public static String getCode(){
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < 6; i++) {
            sb = sb.append( getRandomString());
        }
        return sb.toString();
    }
    
    public static int getRandomString(){
        Random r = new Random();
        int num = r.nextInt(9);
        return num;
    }
    
    public static String getPhones(String[] arr){
        String str = "";
        if (arr!=null&&arr.length >0) {
            for (int i = 0; i < arr.length; i++) {
                str = str + arr[i] + ",";
            }
        }
        return str.substring(0,str.length()-1);
    }

    public static void main(String[] args) {
        int randomString = getRandomString();
        String code = getCode();
        System.out.println(randomString);
        System.out.println(code);
    }

}

注意:第一个参数 login_msg 是配置文件中配置的目的地:

<jms:listener-container destination-type="queue" container-type="default" connection-factory="connectionFactory" acknowledge="auto">
        <!-- 默认注册bean名称,应该是类名首字母小写  -->
        <jms:listener destination="login_msg" ref="smsAuthenCode"/>
    </jms:listener-container>

    
``
监听器 smsAuthenCode 监听到消息之后就会调用发送短信功能。

第二个参数是接口 MessageCreator,这里传入的是匿名内部类,通过 new 接口的形式并实现接口方法。

(5)如果有异常则把 false 放入 map,否则把 true 放入 map,最后返回 map。


@RequestMapping("/phoneLogin")
public String doLogin2 (Model model, @RequestParam(value = "email",required = false) String email,
@RequestParam(value = "password",required = false) String password,
@RequestParam(value = "code",required = false) String code,
@RequestParam(value = "phone_code",required = false) String phone_code,
@RequestParam(value = "state",required = false) String state,
@RequestParam(value = "telephone",required = false) String telephone,
HttpServletRequest request,
HttpServletResponse response
// @RequestParam(value = "pageNum",required = false) Integer pageNum ,
// @RequestParam(value = "pageSize",required = false) Integer pageSize
) {
//判断是否是手机登录
if (StringUtils.isNotBlank(telephone)) {
//手机登录
String yzm = redisTemplate.opsForValue().get( telephone );//从redis获取验证码
if(phone_code.equals(yzm)){
//验证码正确
User user = userService.findByPhone(telephone);
request.getSession().setAttribute("user", user);
model.addAttribute("user", user);
log.info("手机快捷登录成功");
return "/personal/personal";

        }else {
            //验证码错误或过期
            model.addAttribute("error","phone_fail");
            return  "../login";
        }

//后面的怎么也走不到啊 后面的用法是账号登录方法 进行后台判断也是可以的,这里就先不写了。
} else {
//判断号码是否符合条件

        if (StringUtils.isBlank(code)) {
            model.addAttribute("error", "fail");
            return "../login";
        }
        int b = checkValidateCode(code);
        if (b == -1) {
            model.addAttribute("error", "fail");
            return "../login";
        } else if (b == 0) {
            model.addAttribute("error", "fail");
            return "../login";
        }
        password = MD5Util.encodeToHex(Constants.SALT + password);
        User user = userService.login(email, password);
        if (user != null) {
            if ("0".equals(user.getState())) {
                //未激活
                model.addAttribute("email", email);
                model.addAttribute("error", "active");
                return "../login";
            }
            log.info("用户登录登录成功");
            request.getSession().setAttribute("user", user);
            model.addAttribute("user", user);
            return "/personal/personal";
        } else {
            log.info("用户登录登录失败");
            model.addAttribute("email", email);
            model.addAttribute("error", "fail");
            return "../login";
        }

    }

}

login.jsp

<%@ page contentType="text/html;charset=UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<c:set var="ctx" value="${pageContext.request.contextPath }"/>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>登录页面</title>
    <!--引入BootStrap样式-->
    <link href="${ctx}/css/zui/css/zui.min.css" rel="stylesheet">
    <link href="${ctx}/css/zui/lib/uploader/zui.uploader.min.css" rel="stylesheet">
    <style>
        body {
            background: url("/images/4.jpg") no-repeat center fixed;
        }

        .content {
            margin: 50px;
        }

        .login-box {
            background: white;
            box-shadow: 0 0 0 15px rgba(255, 255, 255, .1);
            border-radius: 5px;
            padding: 40px;
        }

        .login-form, .form-group {
            margin-top: 20px;
        }
    </style>
</head>
<body>
<div class="content">
    <!-- logo -->
    <div class="row">
        <img src="images/2.gif">
    </div>
    <!--表单-->
    <div class="row" style="margin-top: 50px">
        <div class="col-sm-6 col-sm-offset-3 col-md-4 col-sm-offset-4 login-box">
            <!--标签页,两种登录方式-->
            <ul class="nav nav-secondary nav-justified" id="ap_login">
                <li id="a_login" class="active"><a data-toggle="tab" href="#account-login">账号登录</a></li>
                <li id="p_login"><a data-toggle="tab" href="#phone-login">手机快捷登录</a></li>
            </ul>
            <!-- 标签页内容,两种表单 -->
            <div class="tab-content">
                <!--普通登录-->
                <div class="tab-pane fade in active" id="account-login">
                    <form id="normal_form" name="form" role="form" class="login-form" action="${ctx}/login/doLogin" method="post">
                        <div class="form-group">
                            <label for="username" class="sr-only">用户名</label>
                            <input type="text" id="username" name="email" onblur="checkUserName();" value="${email}" class="form-control" placeholder="用户名">
                        </div>
                        <div class="form-group">
                            <label for="password" class="sr-only">密码</label>
                            <input type="password" id="password" name="password" onblur="checkPassword();" value="${password}" class="form-control" placeholder="密码">
                        </div>
                        <div class="form-group">
                            <label for="code" class="sr-only">验证码</label>
                            <input type="text" id="code"  name="code" class="form-control" placeholder="验证码" onblur="checkCode()" >
                        </div>

                        <div>
                            <img id="captchaImg" style="CURSOR: pointer" onclick="changeCaptcha()"
                                 title="看不清楚?请点击刷新验证码!" align='absmiddle' src="${ctx}/captchaServlet"
                                 height="18" width="55">
                            <a href="javascript:;"
                               onClick="changeCaptcha()" style="color: #666;">看不清楚</a> <span id="code_span" style="color: red"></span>
                        </div>
                        <div class="form-group">

                            <!-- 多选框 -->
                            <div class="checkbox col-xs-12">
                                <input type="checkbox" name="remember">记住登录状态
                                <c:if test="${error eq 'fail'}">
                                    <span style="color: red" id="back_data">用户名或者密码错误</span>
                                </c:if>
                                <c:if test="${error eq 'active'}">
                                    <span style="color: red" id="back_active">您的账号未激活,请先激活!</span>
                                </c:if>
                                <c:if test="${error eq 'phone_fail'}">
                                    <span style="color: red" id="back_phone">手机验证码错误或者已失效</span>
                                </c:if>
                                <span style="color: green" id="normal_span">${success}</span>

                            </div>
                        </div>
                        <div class="form-group">
                            <button type="button" id="btn" class="btn btn-primary btn-block" onclick="normal_login();">登录</button>
                            <br/>
                            <div>
                                <div style="float: left;"><p>使用其它账号登录&nbsp;&nbsp;&nbsp;</p></div>
                                <div style="margin-left: 20px"><a href="to_login"><img src="${ctx}/images/Connect_logo_1.png"></a></div>
                             </div>
                            <div style="margin-left: 26px;float: right"><a href = "register.jsp" >立即注册</a></div>
                        </div>
                    </form>
                </div>
                <!--手机登录-->
                <div class="tab-pane fade" id="phone-login">
                    <form role="form" class="login-form form-horizontal" id="phone_form" action="${ctx}/login/phoneLogin" method="post">
                        <div class="form-group">
                            <label for="username" class="sr-only">用户名</label>
                            <div class="col-xs-12">
                                <input type="text" id="phone" name="telephone" class="form-control" placeholder="手机号" onblur="checkPhone();">
                                <input type="hidden" id="tab" name="tab"  value="pho-login">
                            </div>
                        </div>
                        <div class="form-group">
                            <label for="password" class="sr-only">密码</label>
                            <div class="col-xs-6">
                                <input type="text" id="verifyCode" name="phone_code" class="form-control" placeholder="验证码" onclick="checkPhoneCode();">
                            </div>
                            <div class="col-xs-6">
                                <button class="btn btn-primary btn-block" id="go">获取验证码</button>
                            </div>
                        </div>
                        <div class="form-group">
                            <!-- 多选框 -->
                            <div class="checkbox col-xs-12">
                                <label>
                                    <input type="checkbox" name="hobbies"> 记住登录状态
                                </label>
                            </div>
                        </div>
                        <span id="phone_span"></span>
                        <div class="form-group">
                            <div class="col-xs-12">
                                <button type="button" id="phone_btn" class="btn btn-primary btn-block">登录</button>
                                <br/>
                                <div style="margin-left: 260px"> <a href = "register.jsp" >立即注册</a></div>
                            </div>
                        </div>
                    </form>
                </div>
            </div>
        </div>
    </div>`
</div>
<script src="${ctx}/js/jquery-3.2.1.min.js"></script>
<script src="${ctx}/css/zui/js/zui.min.js"></script>
<script>
    //校验用户名
    function checkUserName() {
        $("#back_data").text("");
        $("#back_active").text("");
        $("#back_phone").text("");
        var username = $("#username").val();
        username = username.replace(/^\s+|\s+$/g,"");
        if(username == ""){
            $("#normal_span").text("请输入用户名或密码!").css("color","red");
            return false;
        }else{
            $("#normal_span").text("").css("color","green");
            return true;
        }
    }
    //校验密码
    function checkPassword() {
        $("#back_data").text("");
        $("#back_active").text("");
        $("#back_phone").text("");
        var password = $("#password").val();
        password = password.replace(/^\s+|\s+$/g, "");
        if (password == "") {
            $("#normal_span").text("请输入密码!").css("color", "red");
            return false;
        }
        if (password.length < 6) {
            $("#normal_span").text("密码长度少于6位,请重新输入!").css("color", "red");
            return false;
        }

        $("#normal_span").text("").css("color", "green");
        return true;
    }
    //更换验证码
    function changeCaptcha() {
        $("#captchaImg").attr('src', '${ctx}/captchaServlet?t=' + (new Date().getTime()));
    }

    //验证码校验
    var flag_c = false;
    function checkCode() {
        $("#back_data").text("");
        $("#back_active").text("");
        $("#back_phone").text("");
        var code = $("#code").val();
        code = code.replace(/^\s+|\s+$/g,"");
        if(code == ""){
            $("#code_span").text("请输入验证码!").css("color","red");
            flag_c = false;
        }else{
            $.ajax({
                type: 'post',
                url: '/login/checkCode',
                data: {"code": code},
                dataType: 'json',
                success: function (data) {
                    var val = data['message'];
                    if (val == "success") {
                        $("#code_span").text("√").css("color","green");
                        $("#reg_span").text("");
                        flag_c = true;
                    }else {
                        $("#code_span").text("验证码错误!").css("color","red");
                        flag_c = false;
                    }
                }
            });

        }
        return flag_c;
    }

    //密码框回车事件
    $("#password").bind('keypress',function(event){


        if(event.keyCode == 13)

        {
           normal_login();
        }

    });

    //验证码框回车事件
    $("#code").bind('keypress',function(event){


        if(event.keyCode == 13)

        {
            normal_login();
        }

    });

    function normal_login() {
        if(checkUserName() && checkPassword() && checkCode()) {
            $("#normal_form").submit();
        }
    }








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

                        flag2 =  false;

                    }else if(val=="fail1"){
                        $("#phone_span").text("该手机号未激活!").css("color","red");
                        flag2 =  false;
                    }else if(val=="fail2"){
                        //注册
                        $("#phone_span").text("");

                        flag2 =  true;
                    }
                }
            });

        }

        return flag2;
    }



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


    //获取验证码
    $(function () {
        var go = document.getElementById('go');

        go.onclick = function (ev){
            if(!flag2){
                $("#phone_span").text("手机号码非法或者未注册!").css("color","red");
            }else {
                //  发送短信给用户手机..
                // 1 发送一个HTTP请求,通知服务器 发送短信给目标用户
                var telephone =$("input[name='telephone']").val();// 用户输入的手机号
                    // 用户输入手机号校验通过
                    $("#go").attr("disabled", "");
                    countDown(60);

                    $.ajax({
                        method: 'POST',
                        url: '${ctx}/login/sendSms',// 发送验证码给ActiveQM, 同时保存验证码到redis数据库
                        data : {
                            telephone : telephone
                        },
                        success:function(data) {
                            var tt = data["msg"];
                            if(tt){
                                new $.zui.Messager('短信发送成功!', {
                                    type: 'success',
                                    icon:'ok-sign',
                                    actions: [{
                                        name: 'close',
                                        icon: 'remove'
                                    }]
                                }).show();

                            }else{
                                new $.zui.Messager('发送短信出错,请联系管理员!', {
                                    type: 'danger',
                                    icon:'fail',
                                    actions: [{
                                        name: 'close',
                                        icon: 'remove'
                                    }]
                                }).show();
                            }
                        }
                    });
                }


            var oEvent = ev || event;
            //js阻止链接默认行为,没有停止冒泡
            oEvent.preventDefault();
            return false;

        }
    });

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

        return p_flag;
    }
    //登录
    $("#phone_btn").click(function () {

        if(checkPhone()&& checkPhoneCode()){
            // 校验用户名和密码
            $("#phone_span").text("").css("color","red");
            $("#phone_form").submit();
        }else {
            new $.zui.Messager('请输入手机号和6位验证码!', {
                type: 'danger',
                icon:'fail',
                actions: [{
                    name: 'close',
                    icon: 'remove'
                }]
            }).show();
        }

    });

    function GetQuery(key) {
        var search = location.search.slice(1); //得到get方式提交的查询字符串
        var arr = search.split("&");
        for (var i = 0; i < arr.length; i++) {
            var ar = arr[i].split("=");
            if (ar[0] == key) {
                return ar[1];
            }
        }
    }
    //页面加载完成函数
    $(function () {
        var msg = "${phoneError}";
        var phone = "${phoneNum}";
        if(msg == "phone"){
            $("#phone-login").attr("class","tab-pane fade in active")
            $("#p_login").attr("class","active");
            $("#account-login").attr("class","tab-pane fade");
            $("#a_login").attr("class","");
            $("#phone_span").text("短信验证码错误").css("color","red");
            $("#phone").val(phone);
        }
    });
</script>
</body>
</html>

补充:在里在前台验证phone的时候花了一些时间,

@RequestMapping("/checkPhone")
    @ResponseBody
    public Map<String,Object> checkPhone(Model model, @RequestParam(value = "telephone", required = false) String phone) {
        log.debug("注册-判断手机号" + phone + "是否可用来验证登录");
        Map map = new HashMap();
        User user = userService.findByPhone(phone);
       // String state = user.getState();
      //  System.out.println("state:"+state);
        if (user == null) {
            //未注册
            map.put("message", "success");

        }
       if(user !=null){
           System.out.println("user不为空:"+user);
          Integer state = Integer.valueOf(user.getState());
           System.out.println("state:"+state);

           if(state==0){
            map.put("message","fail1");
               System.out.println("map0:"+map);
               return map;
           }
           if(state==1) {
               map.put("message","fail2");
               System.out.println("map1:"+map);
               return map;
           }
       }
        System.out.println("map2:"+map);
        return map;
    }

String state=user.getState(); 我之前这样写根据条件不能正确返回map

Integer state = Integer.valueOf(user.getState());,然后改成这样就能正确返回map
这个坑!!!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容