需求分析
手機快速登錄功能,就是通過短信驗證碼的方式進行登錄。這種方式相對於用戶名密碼登錄方式,用戶不需要記憶自己的密碼,只需要通過輸入手機號並獲取驗證碼就可以完成登錄,是目前比較流行的登錄方式。
手機快速登錄
頁面調整
登錄頁面為/pages/login.html
發送驗證碼
為獲取驗證碼按鈕綁定事件,並在事件對應的處理函數中校驗手機號,如果手機號輸入正確則顯示30秒倒計時效果並發送ajax請求,發送短信驗證碼

<div class="input-row"> <label>手機號</label> <div class="loginInput"> <input v-model="loginInfo.telephone" id='account' type="text" placeholder="請輸入手機號"> <input id="validateCodeButton" @click="sendValidateCode()" type="button" style="font-size: 12px" value="獲取驗證碼"> </div> </div>

<script> var vue = new Vue({ el:'#app', data:{ loginInfo:{}//登錄信息 }, methods:{ //發送驗證碼 sendValidateCode(){ var telephone = this.loginInfo.telephone; if (!checkTelephone(telephone)) { this.$message.error('請輸入正確的手機號'); return false; } validateCodeButton = $("#validateCodeButton")[0]; clock = window.setInterval(doLoop, 1000); //一秒執行一次 axios. post("/validateCode/send4Login.do?telephone=" + telephone). then((response) => { if(!response.data.flag){ //驗證碼發送失敗 this.$message.error('驗證碼發送失敗,請檢查手機號輸入是否正確'); } }); } } }); </script>
在ValidateCodeController中提供send4Login方法,調用短信服務發送驗證碼並將驗證碼保存到redis

//手機快速登錄時發送手機驗證碼 @RequestMapping("/send4Login") public Result send4Login(String telephone){ Integer code = ValidateCodeUtils.generateValidateCode(6);//生成6位數字驗證碼 try { //發送短信 SMSUtils.sendShortMessage(SMSUtils.VALIDATE_CODE,telephone,code.toString()); } catch (ClientException e) { e.printStackTrace(); //驗證碼發送失敗 return new Result(false, MessageConstant.SEND_VALIDATECODE_FAIL); } System.out.println("發送的手機驗證碼為:" + code); //將生成的驗證碼緩存到redis jedisPool.getResource().setex(telephone+RedisMessageConstant.SENDTYPE_LOGIN, 5 * 60, code.toString()); //驗證碼發送成功 return new Result(true,MessageConstant.SEND_VALIDATECODE_SUCCESS); }
提交登錄請求
為登錄按鈕綁定事件
<div class="btn yes-btn"><a @click="login()" href="#">登錄</a></div>

//登錄 login(){ var telephone = this.loginInfo.telephone; if (!checkTelephone(telephone)) { this.$message.error('請輸入正確的手機號'); return false; } axios.post("/member/login.do",this.loginInfo).then((response) => { if(response.data.flag){ //登錄成功,跳轉到會員頁面 window.location.href="member.html"; }else{ //失敗,提示失敗信息 this.$message.error(response.data.message); } }); }
后台代碼
Controller
在health_mobile工程中創建MemberController並提供login方法進行登錄檢查,處理邏輯為:
1、校驗用戶輸入的短信驗證碼是否正確,如果驗證碼錯誤則登錄失敗
2、如果驗證碼正確,則判斷當前用戶是否為會員,如果不是會員則自動完成會員注冊
3、向客戶端寫入Cookie,內容為用戶手機號
4、將會員信息保存到Redis,使用手機號作為key,保存時長為30分鍾

package com.itheima.controller; import com.alibaba.fastjson.JSON; import com.alibaba.dubbo.config.annotation.Reference; import com.aliyuncs.exceptions.ClientException; import com.itheima.constant.MessageConstant; import com.itheima.constant.RedisConstant; import com.itheima.constant.RedisMessageConstant; import com.itheima.entity.Result; import com.itheima.pojo.Member; import com.itheima.service.MemberService; import com.itheima.utils.JedisUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import redis.clients.jedis.JedisPool; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletResponse; import java.util.Date; import java.util.Map; /** * 會員登錄 */ @RestController @RequestMapping("/member") public class MemberController { @Reference private MemberService memberService; @Autowired private JedisPool jedisPool; //使用手機號和驗證碼登錄 @RequestMapping("/login") public Result login(HttpServletResponse response,@RequestBody Map map){ String telephone = (String) map.get("telephone"); String validateCode = (String) map.get("validateCode"); //從Redis中獲取緩存的驗證碼 String codeInRedis = jedisPool.getResource().get(telephone+RedisMessageConstant.SENDTYPE_LOGIN); if(codeInRedis == null || !codeInRedis.equals(validateCode)){ //驗證碼輸入錯誤 return new Result(false,MessageConstant.VALIDATECODE_ERROR); }else{ //驗證碼輸入正確 //判斷當前用戶是否為會員 Member member = memberService.findByTelephone(telephone); if(member == null){ //當前用戶不是會員,自動完成注冊 member = new Member(); member.setPhoneNumber(telephone); member.setRegTime(new Date()); memberService.add(member); } //登錄成功 //寫入Cookie,跟蹤用戶 Cookie cookie = new Cookie("login_member_telephone",telephone); cookie.setPath("/");//路徑 cookie.setMaxAge(60*60*24*30);//有效期30天 response.addCookie(cookie); //保存會員信息到Redis中 String json = JSON.toJSON(member).toString(); jedisPool.getResource().setex(telephone,60*30,json); return new Result(true,MessageConstant.LOGIN_SUCCESS); } } }
服務接口
在MemberService服務接口中提供findByTelephone和add方法
public void add(Member member); public Member findByTelephone(String telephone);
服務實現類
在MemberServiceImpl服務實現類中實現findByTelephone和add方法
//根據手機號查詢會員 public Member findByTelephone(String telephone) { return memberDao.findByTelephone(telephone); } //新增會員 public void add(Member member) { if(member.getPassword() != null){ member.setPassword(MD5Utils.md5(member.getPassword())); } memberDao.add(member); }
Dao接口
在MemberDao接口中聲明findByTelephone和add方法
public Member findByTelephone(String telephone); public void add(Member member);
Mapper映射文件
在MemberDao.xml映射文件中定義SQL語句

<!--新增會員--> <insert id="add" parameterType="com.itheima.pojo.Member"> <selectKey resultType="java.lang.Integer" order="AFTER" keyProperty="id"> SELECT LAST_INSERT_ID() </selectKey> insert into t_member (fileNumber,name,sex,idCard,phoneNumber,regTime,password,email,birthday,remark) values (#{fileNumber},#{name},#{sex},#{idCard},#{phoneNumber},#{regTime},#{password},#{email},#{birthday},#{remark}) </insert> <!--根據手機號查詢會員--> <select id="findByTelephone" parameterType="string" resultType="com.itheima.pojo.Member"> select * from t_member where phoneNumber = #{phoneNumber} </select>