【功能栏】基于session的模拟短信注册功能

框架: spring boot   mybatis-plus    

目录

1.创建user表

​编辑2. mybatis-plus插件

3.导入相关依赖

4.配置文件

 5.前端代码

register.html

style.css

6.后端代码

entity层

mapper层

 sevice层

业务层接口

业务层实现类

controller层

7.调试

1. 未输入手机号的时候,直接点击获取验证码按钮

2.输入手机号,但是格式错误

3.输入手机号,并且格式正确

4.调试的时候验证码错误或者手机重复注册都是还在注册页面

8.代码解析


1.创建user表

注意:  phone这个字段设置的时候最好大于11位

2. mybatis-plus插件

安装了mybatis-plus插件后,可以根据数据库生成代码 

首先连接数据库

然后

 

3.导入相关依赖

muybatis-plus依赖
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.5.2</version>
</dependency>

4.配置文件

server.port=8001
spring.datasource.url=jdbc:mysql://localhost:3306/test2?serverTimezone=GMT
spring.datasource.username=root
spring.datasource.password=1234

 5.前端代码

register.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>register</title>
    <link rel="stylesheet" type="text/css" href="/css/style.css"/>
</head>
<body>
<div class="control">
    <div class="item">
        <div class="active">注册</div>
    </div>
    <div class="content">
        <div style="display: block;">
            <form action="/user/register" method="post">
                <p>请输入手机号</p>
                <input type="tel" placeholder="请输入手机号" name="phone" id="phone"/>

                <input type="text" placeholder="请输入验证码" name="code"/>


                <button type="button">获取验证码</button>

                <p>请输入密码</p>
                <input type="password" placeholder="请输入密码" name="password"/>
                <br/>
                <input type="submit" value="注册"/>
            </form>
            <p>已注册,<a href="/user/login" target="top">去登录</a></p>
        </div>
    </div>
</div>


<script>
    var btn = document.querySelector('button');
    var phoneDom = document.getElementById("phone")
    // 全局变量,定义剩下的秒数
    var time = 59;
    // 注册单击事件  X     这里是获取验证码按钮事件
    btn.addEventListener('click', function () {

        // btn.send('post',"/user/code")
        //判断手机号为空
        if (phoneDom.value !== null && phoneDom.value !== '') {

            //发送请求,生成二维码
            let xhr = new XMLHttpRequest();
            // methods:GET/POST请求方式等,url:请求地址,true异步(可为false同步)
            xhr.open("GET", "/user/code?phone=" + phoneDom.value, true);
            xhr.send();                                            // 发送
            xhr.onreadystatechange = function () {
                if (xhr.readyState == 4 && xhr.status == 200) {   // 成功,接收到数据
                    console.log(xhr.response);                 // 查看返回的数据(可输出 xhr 哈)
                    // 禁用按钮
                    btn.disabled = true;
                    // 开启定时器
                    var timer = setInterval(function () {
                        // 判断剩余秒数
                        if (time == 0) {
                            // 清除定时器和复原按钮
                            clearInterval(timer);
                            btn.disabled = false;
                            btn.innerHTML = '获取验证码';
                        } else {
                            btn.innerHTML = time + '秒';
                            time--;
                        }
                    }, 1000);

                } else if (xhr.status == 404) {
                    // 失败,页面未找到

                }
            }
        } else {
            alert("请输入手机号!")
        }
    });
</script>


</body>
</html>

style.css

*{
    margin: 0;
    padding: 0;
}
body{
    background:#65cea7 ;
}
.control{
    width: 340px;
    background: white;
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%,-50%);
    border-radius: 5px;
}
.item{
    width: 340px;
    height: 60px;
    background: #eeeeee;
}
.item div{
    width: 340px;
    height: 60px;
    display: inline-block;
    color: black;
    font-size: 18px;
    text-align: center;
    line-height: 60px;
    cursor: pointer;
}
.content{
    width: 100%;
}
.content div{

    margin: 20px 30px;
    text-align: left;
}
p{
    color: #4a4a4a;
    margin-top: 30px;
    margin-bottom: 6px;
    font-size: 15px;
}

.content input[type="tel"]{
    width: 100%;
    height: 40px;
    border-radius: 3px;
    border: 1px solid #adadad;
    padding: 0 10px;
    box-sizing: border-box;
}
.content  input[type="text"]{
    width: 55%;
    height: 40px;
    border-radius: 3px;
    border: 1px solid #adadad;
    padding: 0 10px;
    box-sizing: border-box;
}

.content input[type="password"]{
    width: 100%;
    height: 40px;
    border-radius: 3px;
    border: 1px solid #adadad;
    padding: 0 10px;
    box-sizing: border-box;
}
.content button{
    margin-top: 40px;
    width: 40%;
    height: 40px;
    border-radius: 5px;
    color: white;
    border: 1px solid #adadad;
    background: cyan;
    cursor: pointer;
    letter-spacing: 4px;
    margin-bottom: 40px;


}


.content input[type="submit"]{
    margin-top: 40px;
    width: 100%;
    height: 40px;
    border-radius: 5px;
    color: white;
    border: 1px solid #adadad;
    background: cyan;
    cursor: pointer;
    letter-spacing: 4px;
    margin-bottom: 40px;
}
.active{

    background: white;
}
.item div:hover{
    background: #f6f6f6;
}

6.后端代码

entity层

@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName("user")
public class User implements Serializable {

    private static final long serialVersionUID = 1L;

    @TableId(value = "id", type = IdType.AUTO)
    private Integer id;

    private String phone;

    private String password;

    private String  code;

mapper层

@Mapper
public interface UserMapper extends BaseMapper<User> {


}

 sevice层

业务层接口

public interface IUserService extends IService<User> {



    String register(User user, HttpSession session);

    String sendCode(String phone, HttpSession session);
}

业务层实现类

@Slf4j
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {


    @Autowired
    private UserMapper userMapper;


    @Override
    public String sendCode(String phone, HttpSession session) {
        //这里手机号码为空则报空指针,判断不严谨
        if (StringUtils.hasText(phone) && RegexUtil.isMobile(phone)) {
            //生成验证码
            String yzmCode = RandomUtil.randomNumbers(6);

            //保存验证码到session
            session.setAttribute("yzmCode", yzmCode);

            System.out.println("发送短信验证码成功" + yzmCode);
            return "发送短信验证码成功!验证码是:" + yzmCode;
        } else {
            return "手机号格式错误";
        }
    }


    @Override
    public String register(User user, HttpSession session) {
        //判断输入手机号的格式
        if (StringUtils.hasText(user.getPhone()) && RegexUtil.isMobile(user.getPhone())) {
            //从session拿出缓存的验证码
            Object cacheCode = session.getAttribute("yzmCode");
            String code = user.getCode();
            if (cacheCode == null || !cacheCode.equals(code)) {
                return "html/register";
            }
            //3.根据手机号查询用户
            User user1 = query().eq("phone", user.getPhone()).one();
            if (user1 == null) {
                userMapper.insert(user);
                return "html/login";
            }
            session.setAttribute("user1", user1);
            return "html/register";
        }
        return "html/register";
    }
}

controller层

@Controller
@RequestMapping("user")
public class UserController {


    @Autowired
    private IUserService userService;

    @RequestMapping("/code")
    @ResponseBody
    public String sendCode(String phone, HttpSession session) {
        return userService.sendCode(phone, session);
    }



    @RequestMapping("/register")
    public String register(User user, HttpSession session) {
        return userService.register(user, session);
    }
}

工具类(utils)

public class RegexUtil {


    public static boolean isMobile(String str) {
        Pattern p = null;
        Matcher m = null;
        boolean b = false;
        p = Pattern.compile("^[1][3,4,5,8][0-9]{9}$"); // 验证手机号
        m = p.matcher(str);
        b = m.matches();
        return b;
    }
}

 

7.调试

前端页面

1. 未输入手机号的时候,直接点击获取验证码按钮

2.输入手机号,但是格式错误

3.输入手机号,并且格式正确

 

验证码是模拟生成的

 String yzmCode = RandomUtil.randomNumbers(6);

4.调试的时候验证码错误或者手机重复注册都是还在注册页面

8.代码解析

实体类

实体类的属性对应数据user表字段

控制层主要写了两个接口

一个是发送验证码接口,当我们点击前端页面获取验证码按钮的时候,这个接口响应

获取验证码事件

这里主要使用了ajax技术

<script>
    var btn = document.querySelector('button');
    var phoneDom = document.getElementById("phone")
    // 全局变量,定义剩下的秒数
    var time = 59;
    // 注册单击事件  X     这里是获取验证码按钮事件
    btn.addEventListener('click', function () {

        // btn.send('post',"/user/code")
        //判断手机号为空
        if (phoneDom.value !== null && phoneDom.value !== '') {

            //发送请求,生成验证码
            let xhr = new XMLHttpRequest();
            // methods:GET/POST请求方式等,url:请求地址,true异步(可为false同步)
            xhr.open("GET", "/user/code?phone=" + phoneDom.value, true);
            xhr.send();                                            // 发送
            xhr.onreadystatechange = function () {
                if (xhr.readyState == 4 && xhr.status == 200) {   // 成功,接收到数据
                    console.log(xhr.response);                 // 查看返回的数据(可输出 xhr 哈)
                    // 禁用按钮
                    btn.disabled = true;
                    // 开启定时器
                    var timer = setInterval(function () {
                        // 判断剩余秒数
                        if (time == 0) {
                            // 清除定时器和复原按钮
                            clearInterval(timer);
                            btn.disabled = false;
                            btn.innerHTML = '获取验证码';
                        } else {
                            btn.innerHTML = time + '秒';
                            time--;
                        }
                    }, 1000);

                } else if (xhr.status == 404) {
                    // 失败,页面未找到

                }
            }
        } else {
            alert("请输入手机号!")
        }
    });
</script>

控制层调用service的接口里的一个方法

实现类实现该方法

方法如下 

 @Override
    public String sendCode(String phone, HttpSession session) {
        //这里手机号码为空则报空指针,判断不严谨
        if (StringUtils.hasText(phone) && RegexUtil.isMobile(phone)) {
            //生成验证码
            String yzmCode = RandomUtil.randomNumbers(6);

            //保存验证码到session
            session.setAttribute("yzmCode", yzmCode);

            System.out.println("发送短信验证码成功" + yzmCode);
            return "发送短信验证码成功!验证码是:" + yzmCode;
        } else {
            return "手机号格式错误";
        }
    }

1.首先判断手机号的格式

2.如果手机号格式不为空,且手机号格式正确

通过随机生成验证码,这里只是简单的模拟短信验证码,真正的实现这里可以调用相关的方法

3.将验证码保存到session中

4.在控制台输出该验证码

一个是注册接口

  @Override
    public String register(User user, HttpSession session) {
        //判断输入手机号的格式
        if (StringUtils.hasText(user.getPhone()) && RegexUtil.isMobile(user.getPhone())) {
            //从session拿出缓存的验证码
            Object cacheCode = session.getAttribute("yzmCode");
            String code = user.getCode();
            if (cacheCode == null || !cacheCode.equals(code)) {
                return "html/register";
            }
            //3.根据手机号查询用户
            User user1 = query().eq("phone", user.getPhone()).one();
            if (user1 == null) {
                userMapper.insert(user);
                return "html/login";
            }
         
            return "html/register";
        }
        return "html/register";
    }
}

1.判断手机号格式

2.判断输入的验证码和session保存的验证码是否相等

3.根据手机号查询该用户是否存在

  User user1 = query().eq("phone", user.getPhone()).one();

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/148564.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【案例】由coredump引起的思考:程序的加载流程

背景 小米项目的同事&#xff0c;最近遇到了一个crash问题&#xff0c;困扰较久&#xff0c;向我请求帮助。&#xff08;其实是客户指定要求我来分析这个问题&#xff0c;该项目之前是由我负责的&#xff0c;帮客户解决很多较多crash问题。估计是实力得到了客户认可吧&#xff…

使用SSH和SCP传输文件———详细入门教学实践

确保你已经在本地机器上安装了SSH客户端和SCP工具。 获取远程虚拟机的IP地址或主机名以及登录凭据&#xff08;用户名和密码或私钥&#xff09;。 打开终端&#xff08;命令提示符&#xff09;并输入以下命令来传输文件&#xff1a; scp /本地路径/文件 用户名远程虚拟机IP地…

运动蓝牙耳机哪个品牌好?这五款骨传导耳机表现还不错!

作为一个经常跑步运动的人&#xff0c;总感觉运动能够让人暂时远离城市的喧嚣&#xff0c;同时运动也是一种特别好的舒压方法。但跑步的时候如果没有音乐助燃&#xff0c;那是没有灵魂的&#xff0c;这也许就是现代年轻人的矫情吧&#xff0c;我在运动的时候经常会佩戴骨传导耳…

nvm安装node,查看npm版本报错

nvm安装node&#xff0c;使用npm -v报如上图错误&#xff0c;是因为Node版本过高导致&#xff0c;可以降低node版本&#xff0c;使用低一级版本的node. nvm use 16.13.0后来我单独安装node 20.9.0就成功了&#xff0c;不再使用nvm安装Node

mfc140u.dll丢失怎么修复?4种亲测有效的方法分享

在计算机使用过程中&#xff0c;我们可能会遇到各种各样的问题&#xff0c;其中之一就是某些重要的dll文件丢失。DLL文件是动态链接库文件&#xff0c;它们包含了许多程序运行所需的函数和资源。当这些文件丢失或损坏时&#xff0c;可能会导致程序无法正常运行。本文将详细介绍…

完全未接触过软件测试的人,培训两个月就可上岗,这现实吗?

如果你想两个月能学完是可以的&#xff0c;但是只能做一些简单的功能测试&#xff0c;但也只限下面这四种情况 1.自身基础较好&#xff0c;自控力较强 比如一个计算机专业的学生要入行软件测试&#xff0c;可能就不需要进行入门培训了&#xff0c;自己找点视频看看就能很快上…

没有 SegWit 和 Taproot 的比特币序数

序号 &#xff08;Ordinals&#xff09;已成为 BTC 圈子中创建不可替代令牌&#xff08;NFT&#xff09;的热门话题。 它的主要特点是将 NFT 本身完全存储在链上。 我们表明原始的比特币协议已经可以支持它。 Ordinals 不需要任何重大更改&#xff0c;包括 SegWit 和 Taproot。…

骨传导蓝牙耳机哪款好?这五款骨传导耳机闭眼入都不会错!

随着科技的发展&#xff0c;数码产品更新换代的速度也是越来越快&#xff0c;如今无线蓝牙耳机已经占据主流&#xff0c;特别是运动爱好者&#xff0c;很多人都会为自己挑选一款好用的运动耳机&#xff0c;而骨传导耳机异军突起&#xff0c;凭借听歌不入耳、佩戴舒适稳固等特性…

nodejs+express重定向

前言&#xff1a; 本篇代码中需要安装的依赖包包括&#xff1a;request、express 1.常用重定向方法 nodejs中的重定向可以使用.redirect()方法&#xff0c;该方法中可以传两个参数&#xff1a;code和path&#xff0c;code指重定向时&#xff0c;当前访问的这个接口的返回码3…

开发板上网详细教程

开发板上网详细教程 PC端操作开发板操作 写在前面 今天想配置开发板的boa服务器&#xff0c;需要下载sudo apt-get install bison flex&#xff0c;但是一直报错&#xff0c;就蒙蔽了&#xff0c;后来想想真不应该啊&#xff0c;电脑和开发板通信没问题&#xff0c;但也只是如此…

Git笔记简化版

起源 Git是目前世界上最先进的分布式版本控制系统。林纳斯-托瓦兹在开发linux系统时有很多人想有一个平台进行版本控制。当时同类型的版本控制软件是BitKeeper&#xff0c;bitKeep是不开源的。当林纳斯团队无法免费使用它时&#xff0c; 林纳斯花费了一个月左右时间就开发出了…

【算法】最短路径——迪杰斯特拉 (Dijkstra) 算法

目录 1.概述2.代码实现2.1.节点类2.2.邻接矩阵存储图2.3.邻接表存储图2.4.测试 3.扩展3.1.只计算一对顶点之间的最短路径3.2.获取起点到其它节点具体经过的节点 4.应用 本文参考&#xff1a; LABULADONG 的算法网站 1.概述 &#xff08;1&#xff09;在图论中&#xff0c;最短…

个人微信机器人接口

请求URL&#xff1a; http://域名地址/modifyGroupName 请求方式&#xff1a; POST 请求头Headers&#xff1a; Content-Type&#xff1a;application/jsonAuthorization&#xff1a;login接口返回 参数&#xff1a; 参数名必选类型说明wId是String登录实例标识chatRoom…

unity UGUI无限循环滚动居中

最近在做一个ui循环滚动的功能&#xff0c;网上找了半天脚本感觉都和我实际需求不太符合&#xff0c;自己花费一些时间完成了这个功能记录一下。下面开始正题 &#xff0c;我是采用unity自带组件Scroll View来完成&#xff0c;首先设置Scroll View如下图 面板层级结构如下 然…

java springBoot实现RabbitMq消息队列 生产者,消费者

1.RabbitMq的数据源配置文件 # 数据源配置 spring:rabbitmq:host: 127.0.0.1port: 5672username: rootpassword: root#消息发送和接收确认publisher-confirms: truepublisher-returns: truelistener:direct:acknowledge-mode: manualsimple:acknowledge-mode: manualretry:ena…

mysql---主从复制和读写分离

主从复制 主从复制&#xff0c;修改&#xff0c;表里的数据&#xff1a;主mysql上的数据&#xff0c;新增都会同步到从mysql上面试题&#xff1a;mysql的主从复制的模式&#xff1a; 1、异步复制&#xff1a;mysql的默认复制就是异步复制。只要执行完之后&#xff0c;客户端提…

自动化测试Mock神器:轻松模拟HTTP请求..

一、背景 在日常测试过程中或者研发开发过程中&#xff0c;目前接口暂时没有开发完成&#xff0c;测试人员又要提前介入接口测试中&#xff0c;测试人员不仅仅只是简单的编写测试用例&#xff0c;也可以通过一些mock的方法进行来提前根据接口测试的情况进行模拟返回接口的信息…

软件测试/测试开发丨接口自动化测试学习笔记,加密与解密

点此获取更多相关资料 本文为霍格沃兹测试开发学社学员学习笔记分享 原文链接&#xff1a;https://ceshiren.com/t/topic/28019 一、原理 在得到响应后对响应做解密处理&#xff1a; 如果知道使用的是哪个通用加密算法的话&#xff0c;可以自行解决。如果不了解对应的加密算法…

终于有人把VMware虚拟机三种网络模式讲清楚了!

前段时间VMware更新了&#xff0c;你用上最新版了吗&#xff1f; 有几个网工在操作中遇到过各种各样的问题。 比如说由于公司服务器重启导致出现下面的问题&#xff1a;在Xshell里连接虚拟机映射时连接失败&#xff1b;能够连接上虚拟机的映射地址&#xff0c;但git pull时报…

企业常用的几种FTP传输加速方式,最后一种百倍提速

在数字化时代&#xff0c;FTP传输协议仍然是企业之间进行文件传输的重要方式之一。但是&#xff0c;传统的FTP传输速度较慢&#xff0c;对于大文件和海量数据的传输更是显得力不从心。为了提高FTP传输速度&#xff0c;企业们通常会采取一些加速方式。本文将介绍几种企业常用的F…