最新Springboot+mp核心技术外卖入门实战项目(四)
编码阶段四 —— 手机验证码登录
这是对应的视频链接【黑马程序员Java项目实战《瑞吉外卖》,轻松掌握springboot + mybatis plus开发核心技术的真java实战项目-哔哩哔哩】 https://b23.tv/3nr8oMw
大家如果做了可以一起探讨一下,我在其他博客实现了那些视频中没有完成的功能
代码开发-梳理交互过程
- 再登录页面输入手机号,点击[获取验证码]按钮,页面发送ajax请求,在服务端调用短信服务API给指定手机号发送验证码短信
- 在登录页面输入验证码,点击[登录]按钮,发送ajax请求,在服务端处理登录请求
首先是使用原来的User实体类就行,然后搭建相应的框架,先给大家导入两个工具,一个是阿里云发送短信的,另一个是随机生成四或六位数验证码
/** * 短信发送工具类 */public class SMSUtils {/** * 发送短信 * @param signName 签名 * @param templateCode 模板 * @param phoneNumbers 手机号 * @param param 参数 */public static void sendMessage(String signName, String templateCode,String phoneNumbers,String param){DefaultProfile profile = DefaultProfile.getProfile("cn-hangzhou", "", "");IAcsClient client = new DefaultAcsClient(profile);SendSmsRequest request = new SendSmsRequest();request.setSysRegionId("cn-hangzhou");request.setPhoneNumbers(phoneNumbers);request.setSignName(signName);request.setTemplateCode(templateCode);request.setTemplateParam("{\"code\":\""+param+"\"}");try {SendSmsResponse response = client.getAcsResponse(request);System.out.println("短信发送成功");}catch (ClientException e) {e.printStackTrace();}}}/** * 随机生成验证码工具类 */public class ValidateCodeUtils { /** * 随机生成验证码 * @param length 长度为4位或者6位 * @return */ public static Integer generateValidateCode(int length){ Integer code =null; if(length == 4){ code = new Random().nextInt(9999);//生成随机数,最大为9999 if(code < 1000){ code = code + 1000;//保证随机数为4位数字 } }else if(length == 6){ code = new Random().nextInt(999999);//生成随机数,最大为999999 if(code < 100000){ code = code + 100000;//保证随机数为6位数字 } }else{ throw new RuntimeException("只能生成4位或6位数字验证码"); } return code; } /** * 随机生成指定长度字符串验证码 * @param length 长度 * @return */ public static String generateValidateCode4String(int length){ Random rdm = new Random(); String hash1 = Integer.toHexString(rdm.nextInt()); String capstr = hash1.substring(0, length); return capstr; }}
此时得需要先在过滤器中增加两个才能进行正常访问
同样是在过滤器阶段来判断用户登录状态,大家也可以和编码阶段一中的员工管理相对比
//4-2. 判断登录状态,如果已登录,则直接放行 if(request.getSession().getAttribute("user") != null){ log.info("用户已登录,用户id为:{}", request.getSession().getAttribute("user")); Long userId = (Long) request.getSession().getAttribute("user"); BaseContext.setCurrentId(userId); filterChain.doFilter(request, response); return; } log.info("用户未登录");
老师的东西有问题,先在登录页面修改一下
在login.js中添加一个方法:
function sendMsgApi(data){ return $axios({ 'url':'/user/sendMsg', 'method':'post', data })}
这里也有个大坑,记得改一下,不改的话code传不到前端
这些业务也写到controller中了
/** * @author William * @create 2022-04-27 13:29 */@RestController@RequestMapping("/user")@Slf4jpublic class UserController { @Autowired private IUserService userService; /** * 发送手机短信验证码 * @param user * @return */ @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("短信发送失败"); } /** * 移动端用户登录 * @param map * @param session * @return */ @PostMapping("/login") public R<User> login(@RequestBody Map map, HttpSession session){ log.info(map.toString()); //获取手机号 String phone = map.get("phone").toString(); //获取验证码 String code = map.get("code").toString(); //从Session中获取保存的验证码 Object codeInSession = session.getAttribute(phone); //进行验证码的比对(页面提交的验证码和Session中保存的验证码比对) if(codeInSession != null && codeInSession.equals(code)){ //如果能够比对成功,说明登录成功 LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>(); queryWrapper.eq(User::getPhone,phone); User user = userService.getOne(queryWrapper); if(user == null){ //判断当前手机号对应的用户是否为新用户,如果是新用户就自动完成注册 user = new User(); user.setPhone(phone); user.setStatus(1); userService.save(user); } session.setAttribute("user",user.getId()); return R.success(user); } return R.error("登录失败"); }}