springboot项目:瑞吉外卖 前后端 代码、思路 详细分析 part5

这篇具有很好参考价值的文章主要介绍了springboot项目:瑞吉外卖 前后端 代码、思路 详细分析 part5。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

part1
part2
part3
part4
part5 本页

6 移动端短信发送和手机验证码登入

6.1 短信发送
6.2 手机验证码登入

6.1 短信发送

6.1.1整体分析

springboot项目:瑞吉外卖 前后端 代码、思路 详细分析 part5
2.
springboot项目:瑞吉外卖 前后端 代码、思路 详细分析 part5
3. 注册登入阿里云账户。找到短信服务,设置短信签名(上面图片的阿里云、菜鸟裹裹、天猫…),模板等等
springboot项目:瑞吉外卖 前后端 代码、思路 详细分析 part5
4. 设置AccessKey
5. 看帮助文档,导入对应的Util包

6.2 手机验证码登入

6.2.1 整体思路整理

  1. 需求分析springboot项目:瑞吉外卖 前后端 代码、思路 详细分析 part5
  2. 涉及表的操作(数据模型)
    springboot项目:瑞吉外卖 前后端 代码、思路 详细分析 part5
  3. 代码开发思路
    springboot项目:瑞吉外卖 前后端 代码、思路 详细分析 part5
    想要判断当前手机号是否在表中,如果不在,说明是新用户,将改号码保存
  4. 使用浏览器的手机模式查看H5的页面
    springboot项目:瑞吉外卖 前后端 代码、思路 详细分析 part5
  5. 拦截器改造,现在加入移动端的登入(session中是否有user,user是成功登入后设置的),设置threadLocal等信息。
  6. 后端思路:短信发送的controller处理完之后,把发送的验证码存到session中。之后是登入的controller,把前端提交的短信验证码和session中的验证码进行比较,如果手机号和验证码都没错,那就放行(设置一个User的session,拦截器就会放行),同时查数据库,看看有没有对应的手机号,没有的话就插入这条手机号的数据

6.2.2 前端代码分析

  1. login.html显示到页面上的代码如下:
<div id="login" v-loading="loading">
    <div class="divHead">登录</div>
    <div class="divContainer">
        <el-input placeholder=" 请输入手机号码" v-model="form.phone"  maxlength='20'/></el-input>
        <div class="divSplit"></div>
        <el-input placeholder=" 请输入验证码" v-model="form.code"  maxlength='20'/></el-input>
        <span @click='getCode'>获取验证码</span>
    </div>
    <div class="divMsg" v-if="msgFlag">手机号输入不正确,请重新输入</div>
    <el-button type="primary" :class="{btnSubmit:1===1,btnNoPhone:!form.phone,btnPhone:form.phone}" @click="btnLogin">登录</el-button>
</div>
  1. 获取验证码,注意发送请求的参数是sendMsgApi({phone:this.form.phone}),json的格式,后端使用注解@RequestParam接收,可以直接接收到一个对象中,属性含有phone字段
getCode(){
    this.form.code = ''
    //正则表达式验证手机号是否正确
    const regex = /^(13[0-9]{9})|(15[0-9]{9})|(17[0-9]{9})|(18[0-9]{9})|(19[0-9]{9})$/;
    if (regex.test(this.form.phone)) {
        this.msgFlag = false
        //sendMsgApi({phone:this.form.phone}) 一个json,key是phone,value是前端输入的手机号
        this.form.code = (Math.random()*1000000).toFixed(0)
    }else{
        this.msgFlag = true
    }
},

这里的msgFlag作用是对应之前的:<div class="divMsg" v-if="msgFlag">手机号输入不正确,请重新输入</div>,即已经通过了验证,不需要弹出提示信息
正常情况下,通过sendMsgApi发送axios请求,请求到后端发送验证码

function sendMsgApi(data) {
    return $axios({
        'url': '/user/sendMsg',
        'method': 'post',
        data
    })
}
  1. 登入模块,前端只需要给后端传loginApi(this.form),这个form:{phone:‘’“,code:‘’” } 是一个json,需要把phone和前端的code都传给后端,后端之前设置了session:session.setAttribute(phone,code); 进行一个验证就好了。
async btnLogin(){
    if(this.form.phone && this.form.code){
        this.loading = true
        const res = await loginApi(this.form)
        this.loading = false
        if(res.code === 1){
            sessionStorage.setItem("userPhone",this.form.phone)
            window.requestAnimationFrame(()=>{
                window.location.href= '/front/index.html'
            })                           
        }else{
            this.$notify({ type:'warning', message:res.msg});
        }
    }else{
        this.$notify({ type:'warning', message:'请输入手机号码'});
    }
}

6.2.3 后端代码分析

整体思路:短信发送的controller处理完之后,把发送的验证码存到session中。之后是登入的controller,把前端提交的短信验证码和session中的验证码进行比较,如果手机号和验证码都没错,那就放行(设置一个User的session,拦截器就会放行),同时查数据库,看看有没有对应的手机号,没有的话就插入这条手机号的数据文章来源地址https://www.toymoban.com/news/detail-438354.html

  1. 发送短信controller: 前端发送请求的参数是sendMsgApi({phone:this.form.phone}),json的格式,后端使用注解@RequestParam接收,可以直接接收到一个对象中,属性含有phone字段
@PostMapping("/sendMsg")
public R<String> sendMsg(@RequestBody User user, HttpSession session){
    //获取手机号
    String phone = user.getPhone();

    if(StringUtils.isNotEmpty(phone)){
        //生成随机的4位验证码
        String code = ValidateCodeUtils.generateValidateCode(4).toString();
        log.info("code={}",code);

        //调用阿里云提供的短信服务API完成发送短信
        //SMSUtils.sendMessage("瑞吉外卖","",phone,code);

        //需要将生成的验证码保存到Session
        session.setAttribute(phone,code);

        return R.success("手机验证码短信发送成功");
    }

    return R.error("短信发送失败");
}
  1. 注意这里不能再使用User接收,主要是User中没有code验证码属性,解决方法一是使用Dto继承User,方法二是使用map接收。这里用方法二,因为code验证码只需要和session做验证就好了,没有存到数据库里的需求。
/**
     * 登入验证
     * @param map 前端传过来电话和验证码,User没有验证码的属性,接不住,所以用map,也可以用Dto
     * @param session 验证成功了,就把user存入session,拦截器那边放行
     * @return
     */
    @PostMapping("/login")
    public RetObj loginController(@RequestBody Map<String,String> map, HttpSession session){
        String phone = map.get("phone");
        String code = map.get("code");
        String sessionCode = session.getAttribute(phone).toString();
        if (StringUtils.isNotBlank(sessionCode) && code.equals(sessionCode)){
            //用户名秘密验证成功!
            //先查电话号码在不在数据库里,如果不在,就要保存
            LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
            lambdaQueryWrapper.eq(User::getPhone,phone);
            User user = userService.getOne(lambdaQueryWrapper);
            if (user ==  null){
                //存入数据库
                User user1 = new User();
                user1.setPhone(phone);
                user1.setStatus(1);
                userService.save(user1);
                //session.setAttribute("user",user1.getId());
            }else {
                session.setAttribute(Contants.SESSION_USERID,user.getId());
            }
            return RetObj.success("登入成功!");
        }else {
            return RetObj.error("登入失败!");
        }
  1. 写完之后配置拦截器,有两个类要配置
package cn.edu.uestc.ruijitakeout.common.interceptor;
@Slf4j
public class LoginInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String uri = request.getRequestURI();
        log.info("当前路径:{}", uri);

        /**
         * HandlerMethod=>Controller中标注@RequestMapping的方法
         *  需要配置静态资源不拦截时,添加这块逻辑  => 前后端分离项目
         *
         */
        // 是我们的controller中的方法就拦截,如果不是的话,放行,给加载静态资源
        if (!(handler instanceof HandlerMethod)) {
            log.info("是静态资源或非controller中的方法,放行");
            return true;
        }

        //1-通过session判断是否登入
        if (request.getSession().getAttribute(Contants.SESSIONLOGIN) != null) {
            log.info("用户已经登入,id={}", request.getSession().getAttribute(Contants.SESSIONLOGIN));

            //进入拦截器后,给threadLocal绑定session,让后面需要的公共字段自动填充的时候,填充这个updateUser
            //每次http请求,会分配一个新的线程来处理
            BaseContext.setThreadLocal((Long) request.getSession().getAttribute(Contants.SESSIONLOGIN));
            log.info("拦截器这里设置了ThreadLocal,值为:{}",(Long) request.getSession().getAttribute(Contants.SESSIONLOGIN));
            log.info("当前线程id={}",Thread.currentThread().getId());
            return true;

        } else if (request.getSession().getAttribute(Contants.SESSION_USERID) != null) {
            log.info("用户已经登入,id={}", request.getSession().getAttribute(Contants.SESSION_USERID));

            //进入拦截器后,给threadLocal绑定session,让后面需要的公共字段自动填充的时候,填充这个updateUser
            //每次http请求,会分配一个新的线程来处理
            BaseContext.setThreadLocal((Long) request.getSession().getAttribute(Contants.SESSION_USERID));
            log.info("拦截器这里设置了ThreadLocal,值为:{}",(Long) request.getSession().getAttribute(Contants.SESSION_USERID));
            log.info("当前线程id={}",Thread.currentThread().getId());
            return true;
        }
        //这里应该跳转到登入页面,如何做?
        //5、如果未登录则返回未登录结果,通过输出流方式向客户端页面响应数据
        log.info("用户未登入,通过输出流方式向客户端页面响应数据,打回登入页面");
        response.getWriter().write(JSON.toJSONString(RetObj.error("NOTLOGIN")));//与前端request.js中的代码呼应
        return false;
    }

package cn.edu.uestc.ruijitakeout.common.config;
@Slf4j
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
    /**
     * 拓展消息转换器
     * @param converters
     */
    @Override
    public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
        log.info("拓展消息转换器成功加载");
        //创建消息转换器对象
        MappingJackson2HttpMessageConverter messageConverter = new MappingJackson2HttpMessageConverter();
        //设置对象转换器,底层使用Jackson将Java对象转为json
        messageConverter.setObjectMapper(new JacksonObjectMapper());
        //将上面的消息转换器对象追加到mvc框架的转换器集合中
        converters.add(0,messageConverter);
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        //重写方法,添加拦截器方法
        registry.addInterceptor(loginInterceptor())
                //拦截哪些路径
                .addPathPatterns("/**")
                //不拦截路径
                .excludePathPatterns("/employee/backend/page/login/login.do",
                        //"/backend/**",
                        "/employee/backend/page/login/logout.do",
                        //"/front/**",
                        "/error",
                        "/user/**"


                );
    }

    @Bean
    public LoginInterceptor loginInterceptor(){
        return new LoginInterceptor();
    }

}

到了这里,关于springboot项目:瑞吉外卖 前后端 代码、思路 详细分析 part5的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【SpringBoot项目实战+思维导图】瑞吉外卖①(项目介绍、开发环境搭建、后台登陆/退出功能开发)

    全文主体框架来源于黑马瑞吉外卖的项目资料,我在文中会嵌入如下五个方面的个人内容: 项目中易发生错误的地方 项目中涉及的一些难理解知识点 一些遗忘知识点的回顾 业务的多种实现方法 我在做项目时的思考和一些踩坑 作为一名软件开发工程师,我们需要了解在软件开

    2024年02月05日
    浏览(41)
  • 瑞吉外卖项目——瑞吉外卖

    需求分析:产品原型、需求规格说明书 设计:产品文档、UI界面设计、概要设计、详细设计、数据库设计 编码:项目代码、单元测试 测试:测试用例、测试报告 上线运维:软件环境安装、配置 项目经理:对整个项目负责,任务分配、把控进度 产品经理:进行需求调研,输

    2023年04月26日
    浏览(80)
  • 基于SpringBoot+Redis的前后端分离外卖项目-苍穹外卖(四)

    1.1 需求分析与设计 1.1.1 产品原型 在员工管理列表页面点击 “编辑” 按钮,跳转到编辑页面,在编辑页面回显员工信息并进行修改,最后点击 “保存” 按钮完成编辑操作。 修改页面原型 : 注:点击修改时,数据应该正常回显到修改页面。 1.1.2 接口设计 根据上述原型图分

    2024年02月05日
    浏览(36)
  • 基于SpringBoot+Redis的前后端分离外卖项目-苍穹外卖集成Redis(九)

    1.1 Redis的Java客户端 Redis 的 Java 客户端很多,常用的几种: Jedis Lettuce Spring Data Redis Spring 对 Redis 客户端进行了整合,提供了 Spring Data Redis,在Spring Boot项目中还提供了对应的Starter,即 spring-boot-starter-data-redis。 1.2 Spring Data Redis使用方式 1.2.1 介绍 Spring Data Redis 是 Spring 的一部分

    2024年02月05日
    浏览(40)
  • 项目笔记-瑞吉外卖(全)

    1.对后端返回请求值的分析 2.对不同种请求参数的分析 3.事务管理 1.软件开发整体介绍 2.项目整体介绍⭐️ 后端:管理菜品和员工信息 前台:通过手机端,可以浏览菜品和添加客户端 开发项目流程: 实现基本需求,用户能在手机浏览器访问 对移动端应用改进,使用微信小程

    2024年02月07日
    浏览(27)
  • 瑞吉外卖项目记录

    本文为个人学习黑马《瑞吉外卖》项目后进行的项目总结,更偏向于对自己编写文本能力的锻炼以及对项目知识点的简短记录。因为个人能力问题,其中可行性分析和测试部分只进行了小标题的陈列,并没有进行编辑。对《瑞吉外卖》项目感兴趣的朋友也可以浏览本文后再去

    2024年02月05日
    浏览(25)
  • 瑞吉外卖项目----(2)缓存优化

    将项目推送到远程仓库里,教程在git 提交远程仓库前建议取消代码检查 创建新的分支v1.0(用于实现缓存优化)并推送到远程仓库 1.1.1 maven坐标 导入spring-data-redis的maven坐标: 1.1.2 配置文件 在application.yml中加入redis相关配置: 1.1.3 配置类 在项目中加入RedisConfig 1.2.1 实现思路

    2024年02月14日
    浏览(31)
  • 基于SpringBoot+Redis的前后端分离外卖项目-苍穹外卖微信小程序端(十一)

    1.1 问题说明 用户端小程序展示的菜品数据都是通过查询数据库获得,如果用户端访问量比较大,数据库访问压力随之增大。 结果 :系统响应慢、用户体验差 1.2 实现思路 通过Redis来缓存菜品数据,减少数据库查询操作。 缓存逻辑分析: 每个分类下的菜品保存一份缓存数据

    2024年01月24日
    浏览(39)
  • 基于SpringBoot+Redis的前后端分离外卖项目-苍穹外卖微信小程序端(九)

    1.1 入门 在进行微信登录之前我们要先知道HttpClient是什么,它是Apache Jakarta Common 下的子项目,可以用来提供高效的、最新的、功能丰富的支持 HTTP 协议的客户端编程工具包,并且它支持 HTTP 协议最新的版本和建议。 HttpClient作用: 发送HTTP请求 接收响应数据 HttpClient应用场景

    2024年02月03日
    浏览(38)
  • 基于SpringBoot+Redis的前后端分离外卖项目-苍穹外卖微信小程序端(十二)

    1.1.1 产品原型 用户可以将菜品或者套餐添加到购物车。对于菜品来说,如果设置了口味信息,则需要选择规格后才能加入购物车;对于套餐来说,可以直接点击+将当前套餐加入购物车。在购物车中可以修改菜品和套餐的数量,也可以清空购物车。 效果图: 1.1.2 接口设计 通过

    2024年01月18日
    浏览(32)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包