千家信息网

Vue怎么邮箱注册和短信注册登录页面

发表于:2024-09-21 作者:千家信息网编辑
千家信息网最后更新 2024年09月21日,这篇文章主要讲解了"Vue怎么邮箱注册和短信注册登录页面",文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习"Vue怎么邮箱注册和短信注册登录页面"吧!前端技
千家信息网最后更新 2024年09月21日Vue怎么邮箱注册和短信注册登录页面

这篇文章主要讲解了"Vue怎么邮箱注册和短信注册登录页面",文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习"Vue怎么邮箱注册和短信注册登录页面"吧!

  1. 前端技术栈:Vue-Cli

  2. 前端软体:WebStorm 2020.3

  3. 前端样式: Bootstrap

  4. 后端技术栈:SpringBoot

  5. 后端软体:IntelliJ IEDA2019

  6. JavaJDK:1.8

  7. 服务器:阿里云Centos 7

  8. 其他:MyBatis,Redis,MySql,Docker,Shiro

  1. 项目源码:shoppingProject01_pub : version6.0

  2. 项目参考:Project05;不良人_Vue-Cli;不良人_Redis;不良人_Axios;尚硅谷_Redis

  3. 项目功能:
    1)邮箱注册登录:
    用户应用邮箱注册点击提交后,网站会给用户发送邮件附带激活码链接,用户点击链接实现账号激活传送门。
    2)短信注册登录:
    用户应用手机号注册时,点击"获取验证码"按钮,手机会接收到网站发送的短信附带验证码。基于Redis实现了验证码有效期5分钟,每个手机号只能获取三次短信验证码传送门。
    3)alipay支付:
    通过下载Android版支付宝沙箱app用户可通过alipay扫码购买网站上的商品,后台MySql会记录该订单行为传送门,网页展示如图1所示。

图1 商品展示页面

4)用户小分级:
当用户扫码购买年度VIP会员后,购买网站上的商品一律半价,后台MySql记录用户角色的变更。
5)用户积分排行榜:
用户购买商品会增加自己的积分,网页展示如图2所示。

图2 排行榜展示页面
  1. 项目中遇到的大坑:
    1)邮件发送功能本地测试通过,服务器端测试Bug频出,解决办法。
    2)项目在服务器部署后,无法连接服务器上的Redis。解决办法:(1)将Redis在服务器部署而非Docker;(2)将Redis端口改为7000;(3)防火墙active状态下放行服务器和阿里云的7000端口;(4)修改Redis.conf文件。
    3)git上传本地源码到gitee,误操作导致本地源码被gitee上的旧代码覆盖,第二天才发现。解决办法:因为在服务器上留有源码的jar包,通过反编译工具jd_gui救回半条命。另外git上传文件参考传送门。

1 Vue-Cli模块说明:

1.1 Vue-Cli的概述:

1)以前后端分离、单页面web应用(SPA)为特点,Vue-Cli可以创建一个Vue项目,这个项目存在脚手架规范。Vue-Cli的优势如下:
(1) 基于脚手架规范的开发会变得很灵活。
(2) Vue-Cli基于webpack构建并带有合理的默认配置,打包工具webpack能够聚合单页面和各种开发组件。
(3) Vue-Cli是一个丰富的官方插件集合,继承了前端生态中最好的工具。

2)安装过程:
(1) 安装WebStorm(用于开发),安装node.js,安装vue-cli,安装axios(用于发起跨域请求),引入bootstrap样式。

3)部署过程:

npm run build               # 在WebStorm终端执行,生成dist文件夹docker pull nginx:1.19.10   # 不建议Vue-cli项目部署到tomcat,因为tomcat属于动态服务器,启动需要java环境,是为了解析动态语言jsp的;像纯静态的就部署到静态服务器nginx上。mkdir html                  # 为了做docker容器内外的数据卷映射mv dist/ html/docker run -p 80:80 --name nginx01 -d -v /root/html/dist/:/usr/share/nginx/html nginx:1.19.10  # 数据卷映射# 此时可访问  http://120.79.133.235:80/index.html

4)Vue-Cli开发要点:
(1)在WebStorm中,开发过程主要面向src文件,如图3所示:

图3 WebStorm目录


[1] 首先掌握路由(router)和组件(components[公有组件],views[私有组件]),组件就是一个个"页面",组件建立后要向路由进行注册; [2] asserts封装了bootstrap样式,并在main.js中被导入; [3] 为了发送跨域请求,在utils中封装了axios实例,代码如下:

import axios from 'axios'// 创建默认实例const instance = axios.create({  baseURL: 'http://120.79.133.235:8989/eb',  // timeout: 10000,});// 请求拦截器instance.interceptors.request.use(config=>{  console.log("请求拦截器");  return config;})// 响应拦截器instance.interceptors.response.use(response=>{  console.log("响应拦截器");  return response;}, err=>{  console.log("响应出现错误时进入的拦截器");});// 暴露instance实例对象export default instance;

在各组件中,对于后端的get和post请求方法如下:

// Get请求// 向后端接口发当前页码,获取当前页面的商品Listinstance.get("/item/findAllItem?page="+this.page).then(res=>{        that.items = res.data.items;        that.totalPage = res.data.totalPage;        that.page = res.data.page;      });// Post请求// 向后端接口发送当前商品id和用户id,获取商品购买状态instance.post("/order/alipay/callback",{itemId:this.itemid,userId:this.user.id}).then(res=>{        if ( res.data.code == 20000 ) {          alert("提示:您已购买该商品");        } else {          alert("提示:您未购买该商品");        }      });    }

[4] 组件之间的跳转和传值方法如下:

// 跳转到MailReg组件this.$router.push({name:"MailReg"});// 跳转到item组件,并传递当前商品的idthis.$router.push({path:"/item",query:{ItemId:myid}});// item组件接收方法:this.itemid = this.$route.query.ItemId;// 另外不同组件可以依据token获取登录用户信息,需要用到redis,详见下文

2 用户积分排行榜模块说明:
1.1 Reids概述:
1) Redis是一种基于内存的数据存储NoSql;
2) Redis支持丰富的数据类型(String, List, Set, ZSet, Hash);
3) Redis有两种持久化方法: (1)快照(snapshot)存储,也叫rdb持久化,保存当前时刻的数据状态;(2) AOF(append only file)存储,将所有redis的写命令记录到日志文件中,Redis支持持久化间隔最快也是一秒,所以它是事务不安全的,即是可能丢失数据的。
4)Redis的应用场景:
(1) 利用Redis字符串完成项目中手机验证码存储的实现。------本项目采用
(2) 利用Redis字符串类型完成具有时效性的业务功能,如订单还有40分钟即将关闭。
(3) 利用Redis实现分布式集群系统中的Session共享。
(4) 利用Redis的ZSet数据类型(可排序set类型:元素+分数)实现排行榜功能。 ------本项目采用
(5) 利用Redis完成分布式缓存。 ------本项目实现MySql中数据的缓存
(6) 利用Redis存储认证之后的token信息。 ------非常方便,本项目采用。
(7) 利用Redis解决分布式集群系统中分布式锁问题。

1.2 基于Redis实现前端组件从后端获取用户信息
Step1:前端Login.vue组件中用户输入登录信息提交的接口如下:

// 这里调用了后端/user/login接口,获取当前登录用户的token,存入Session的localStorage中,在后续网页浏览过程中可随时调取这个tokeninstance.post("/user/login",this.user).then(res=>{        if ( res.data.state ) {          alert(res.data.msg+",点击确定进入主页");          // 前端存储token信息          localStorage.setItem("token",res.data.token);          that.$router.push({path:"/itemList"});        } else {          alert(res.data.msg);          that.user = {};        }      });

Step2:后端/user/login接口实现如下:

// Controller层@PostMapping("login")public Map loginAccount(@RequestBody User user, HttpSession session) {    return userService.loginAccount(user, session);}// Service层// 情况3:查询到一个用户时// 获取主体对象try {     Subject subject = SecurityUtils.getSubject();     subject.login(new UsernamePasswordToken(user.getName(), user.getPassword()));     User userDB = userListDB.get(0);     String token = session.getId();     if (userDB.getScore() == null) {           userDB.setScore(0.0);           userDAO.updateUserScore(userDB);     }     redisTemplate.opsForValue().set("TOKEN_" + token, userDB, 30, TimeUnit.MINUTES);     redisTemplate.opsForZSet().add("userRank", userDB, userDB.getScore());     map.put("token", token);     map.put("state",true);     map.put("msg","登录成功");     return map;     ...

Redis整合SpringBoot有两种Template,即RedisTemplate和StringRedisTemplate。其中StringRedisTemplate是RedisTemplate的子类,两个方法基本一致,不同之处在于操作的数据类型不同,RedisTemplate中的两个泛型都是Object,意味着存储的key和value都可以是一个对象,而StringRedisTemplate的两个泛型都是String,意味着StringRedisTemplate的key和value都只能是字符串。
在Step2中,我将token和数据库中的用户信息userDB绑定在一起存入了Redis中,后续前端组件获取登录用户信息的代码如下:

// 从localStorage获取tokenlet token = localStorage.getItem("token");let that = this;// 发送axios请求,根据token获取用户信息instance.get("/user/token?token="+token).then(res=>{that.user = res.data;console.log(that.user);})

后端/user/token的接口如下:

@GetMapping({"token"})public User findUser(String token) {   System.out.println("接收的token信息:" + token);   return (User)redisTemplate.opsForValue().get("TOKEN_" + token);}

Step3:用户退出登录时,应消除浏览器中对应的token,后端接口代码如下:

    // 退出登录    @DeleteMapping({"logout"})    public Map logout(String token) {        Map map = new HashMap<>();        try {            redisTemplate.delete("TOKEN_" + token);            Subject subject = SecurityUtils.getSubject();            subject.logout();            map.put("state", true);            map.put("msg", "提示:退出账户成功");            return map;        } catch (Exception e) {            e.printStackTrace();            map.put("state", false);            map.put("msg", "提示:退出账户失败");            return map;        }    }

1.3 基于Redis的用户积分排行榜实现
MySql中的用户信息如图4所示:

图4 MySql中的用户信息


Redis中的UserRank如图5所示:

图5 Redis中的UserRank

Step1:当用户登录时,他的首要任务是接入UserRank对应的信息,后端代码如下:

if (userDB.getScore() == null) {    userDB.setScore(0.0);    userDAO.updateUserScore(userDB);}    redisTemplate.opsForValue().set("TOKEN_" + token, userDB, 30, TimeUnit.MINUTES);    redisTemplate.opsForZSet().add("userRank", userDB, userDB.getScore());

userDB是数据库中当前登录用户的信息(一定是有的,你注册了,对吧?),若用户首次登录我将他的分数在数据库设置为0.0,之后我在Redis的ZSet中加入这个用户,你知道,Set集合不会存储重复key值的元素,因此不会同一个用户出现在UserRank中两次。两个template完成了token绑定User,User绑定UserRank中Score的过程,之后的分数更新过程会反复使用这两个template实现。
Step2:当用户信息更新时,相应的与用户信息有关的两个template都要发生变化,代码如下:

// key值序列化redisTemplate.setKeySerializer(new StringRedisSerializer());// 由当前用户的token获取当前用户的信息User firstUser = (User)redisTemplate.opsForValue().get("TOKEN_" + token);// 删除zSet中的当前用户 redisTemplate.opsForZSet().remove("userRank", firstUser);// 产生新的当前用户(昵称改变)List userListDB = this.userDAO.selectUserByName(user.getName());User secondUser = userListDB.get(0);// 更新token中当前用户的信息redisTemplate.opsForValue().set("TOKEN_" + token, secondUser, 30, TimeUnit.MINUTES);// 产生zSet中的当前用户redisTemplate.opsForZSet().add("userRank", secondUser, secondUser.getScore());

Step3:当用户扫码支付时,首次进入的后端controller如下:

// 支付单件商品    @GetMapping("payForItem")    public byte[] alipay(String itemid,String userid, String token) {        this.token = token;        log.info("itemid=====>"+itemid);        log.info("userid=====>"+userid);        PayVo payVo = new PayVo();        payVo.setItemId(itemid);        payVo.setUserId(userid);        System.out.println(payVo.getUserId());        return alipayService.alipay(payVo);    }

在alipayService有一个小型用户分级,即vip用户购物价格减半:

            // 1:支付的用户            String userId = payVo.getUserId();            // my 1: 依据用户id查询用户            User user = userService.selectUserById(Integer.valueOf(userId));            // 依据商品id查询商品            Item item = itemService.getItemById(payVo.getItemId());            // my 1: 依据用户id查询用户            if ( item == null ) return null;            // 2: 支付金额            String tempMoney = item.getPrice().toString();            String money = "";            if ( user.getRole().equals("normal") ) {                money = tempMoney;            }            if ( user.getRole().equals("vip") ) {                Double tempMoney2 = Double.valueOf(tempMoney)*0.5;                money = String.valueOf(tempMoney2);            }

在payForItem相同文件下,调用了payCommonService,在这里会实现用户积分更新和用户等级更新:

payCommonService.payUserPublic(bodyJsonObject, userId, user.getName(), orderNumber, tradeno, "alipay", this.token);

将"VIP"这件商品的id设置为"666",当用户购买该商品时,当前用户更新过程如下:

if ( itemId.equals("666") ) {            int myuserId = Integer.valueOf(userId);            User userDB = userService.selectUserById(myuserId);            // key值序列化            this.redisTemplate.setKeySerializer(new StringRedisSerializer());            // 由当前token获取当前用户信息            User firstUser = (User)redisTemplate.opsForValue().get("TOKEN_" + token);            // 由当前用户信息删除当前用户zSet            redisTemplate.opsForZSet().remove("userRank", firstUser);            // 更新当前用户信息身份            userDB.setRole("vip");            // 更新当前用户新身份的分数            userService.updateUserRole(userDB);            List userListDB = this.userDAO.selectUserByName(userDB.getName());            // 获取当前新身份用户的完整信息            User secondUser = userListDB.get(0);            // 更新当前token对应的当前用户            redisTemplate.opsForValue().set("TOKEN_" + token, secondUser, 30, TimeUnit.MINUTES);            // 设置当前用户的zSet            redisTemplate.opsForZSet().add("userRank", secondUser, secondUser.getScore().doubleValue());        }

当前用户积分更新过程如下:

        // 更新当前用户的积分        double tempScore = Double.valueOf(orderDetail.getPrice()) * 0.3;        String key1 = "TOKEN_" + token;        // 由当前token获取当前用户        User user = (User)redisTemplate.opsForValue().get(key1);        // 更新当前用户的zSet分数        redisTemplate.opsForZSet().incrementScore("userRank", user, tempScore);        // 获取当前用户的zSet分数        double newScore = redisTemplate.opsForZSet().score("userRank", user);        // 删除当前用户的zSet(因为要更新当前用户的信息,将当前用户在数据库中的分数进行同步)        redisTemplate.opsForZSet().remove("userRank", new Object[] { user });        user.setScore(newScore);        userDAO.updateUserScore(user);        // 更新token对应的当前用户的信息        redisTemplate.opsForValue().set(key1, user);        // 新增当前用户的zSet        redisTemplate.opsForZSet().add("userRank", user, newScore);

感谢各位的阅读,以上就是"Vue怎么邮箱注册和短信注册登录页面"的内容了,经过本文的学习后,相信大家对Vue怎么邮箱注册和短信注册登录页面这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是,小编将为大家推送更多相关知识点的文章,欢迎关注!

0