使用HttpClient短信网关接口实现手机号验证码注册
确保手机号正确,利用短信网关接口发送验证码,判断验证码一致
步骤:
1、导入HttpClient的依赖:httpclient4.5.5.jar
2、reg页面的js(判断手机号是否为空,手机号的正确性,ajax发送phone的value异步请求,返回json是否符合)
3、controller层编写获取手机号返回json信息
4、在UserServiceImpl中,根据phone调用httpClient网关接口 ***
准备UserServiceImpl中需要的
实体类:返回前端的json类、前端传输过来的实体类
工具类:将数据实体类存入session的工具类、时间常量类、计算时间类、随机验证码类
5、在controller中判断session中的phone并且验证码是否与页面传输的一致,true运行注册
保证手机号的有效性
具体实现:
1、导入HttpClient的依赖
<!-- httpclient短信网关 --> <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>4.5.5</version> </dependency>
2、reg页面的js的编写
/* 短信验证码验证 */ $("body").on("click", "#getPhoneCheckCode", function () { //新添加的,也有效 var formId = 'form_register'; var value = $.trim($("#" + formId + " input[name='telephone']").val()); var errTag = $("#error"); errTag.html(""); var length = value.length; if (length == 0) { errTag.html("请输入手机号码"); }else { var mobile = /^1[3,4,5,6,7,8,9]\d{9}$/; if (!mobile.test(value)) { errTag.html("请输入正确的手机号码"); } else { $("#getPhoneCheckCode").addClass('disabled'); $("#getPhoneCheckCode").prop('disabled', true); $.ajax({ url: "/house/sendCheckCode", type: "post", cache: false, dataType: 'json', data: { phone: value }, success: function (msg) { if (msg.status) { errTag.text('验证码已发送到您的手机'); var time = 60; var t = setInterval(function () { $("#getPhoneCheckCode").text(time + "S后重新获取"); time--; if (time == 0) { clearInterval(t); $("#getPhoneCheckCode").text("获取验证码"); $("#getPhoneCheckCode").prop('disabled', false); $("#getPhoneCheckCode").removeClass('disabled'); } }, 1000); } else { errTag.text('未知错误'); } } }); } } });
3、controller层编写获取手机号返回json信息
//发送验证码 @PostMapping("/sendCheckCode") @ResponseBody public JSONResult sendCheckCode(String phone) throws Exception{ JSONResult jsonResult = userService.sendCode(phone); System.out.println(jsonResult.isStatus()); return jsonResult; }
4、编写业务层前需要做的准备
①json返回数据的对象类(是否成功、显示信息)
public class JSONResult { private boolean status = true;//表示成功 private String msg;//显示消息
②前端传过来的信息(手机号、验证码,最后一次点击发送验证码的时间)
public class VerifyCodeVo { /**手机号码*/ private String phone; /**验证码*/ private String verifyCode; /**最后一次发送时间*/ private Date lastTime;
③操作session域的工具类,用于将前端传过来的信息保存在session中
public class UserContext { //定义一个session名称的常量 public static final String VERIFY_CODE_IN_SESSION = "verifyCodeInSession"; //得到httpsession private static HttpSession getSession() { //SpringMVC 提供一个RequestContextHolder工具类, 得到Http Servlet API: request,response,session return ((ServletRequestAttributes)(RequestContextHolder.getRequestAttributes())).getRequest().getSession(); } //创建一个session对象 public static void setVerifyCode(VerifyCodeVo verifyCodeVo) { getSession().setAttribute(VERIFY_CODE_IN_SESSION, verifyCodeVo); } //获取session对象 public static VerifyCodeVo getCurrentVerifyCode() { return (VerifyCodeVo) getSession().getAttribute(VERIFY_CODE_IN_SESSION); } }
④编写一个常量类,用于存放设置下一次运行发送验证码的时间、验证码有效时间
public class SystemConstant { /**发送验证码的时间间隔: 单位:秒*/ public static final int BETWEEN_SEND_TIME = 60; /**验证码的有效时间: 5分钟*/ public static final int VERIFYCODE_VALIDATE_TIME=5*60;
⑤编写一个时间工具类,用于计算当前时间减去上一次点击的时间,判断是否允许发送
public class DateUtils { public static long betweenTime(Date d1, Date d2) { return Math.abs((d1.getTime() - d2.getTime())/1000); }
⑥编写一个随机数工具类,随机生成指定位数验证码
public class RandomUtils { public static String randomNumber(int length) { String num = Math.random()+""; return num.substring(2, length+2); }
5、在UserServiceImpl中,根据phone参数调用httpClient网关接口
//发送验证码 @Override public JSONResult sendCode(String phone) throws Exception { //创建一个JSONResult对象,用于返回数据 JSONResult jsonResult = new JSONResult(); //获取存在session中的手机短信信息(手机号,验证码,发送时间) VerifyCodeVo currentVerify = UserContext.getCurrentVerifyCode(); //1.判断时间间隔大于BETWEEN_SEND_TIME. 大于: 表示可以发送 //等于空表示是第一次点击,允许发送 //当前时间减去上一次发送的时间 如果大于,验证码的有效时间,可以发送 if(currentVerify == null || DateUtils.betweenTime(new Date(), currentVerify.getLastTime()) > SystemConstant.VERIFYCODE_VALIDATE_TIME){ //发送,使用HttpClient发送, 发送的post //1.创建客户端 CloseableHttpClient httpClient = HttpClientBuilder.create().build(); //2. 准备参数 URI uri = null; List<NameValuePair> params = new ArrayList<>(); params.add(new BasicNameValuePair("Uid", "xiao"));//jing2672711802 params.add(new BasicNameValuePair("Key", "d41d8cd98f00b204e980")); params.add(new BasicNameValuePair("smsMob", phone)); //随机生成的短信验证码,自定义长度为4位 String verifyCode = RandomUtils.randomNumber(4); params.add(new BasicNameValuePair("smsText", "发给胡老师:验证码"+verifyCode+"【我的小宝贝】")); uri = new URIBuilder().setScheme("http") .setHost("utf8.api.smschinese.cn/") .setParameters(params) .build(); //3.创建一个HttpPost请求 HttpPost httpPost = new HttpPost(uri); //4.发送请求 CloseableHttpResponse httpResponse = httpClient.execute(httpPost); HttpEntity entity = httpResponse.getEntity(); int result = Integer.parseInt(EntityUtils.toString(entity)); if(result<= 0) { //发送失败 throw new RuntimeException("调用短信网关出错了,错误代码:"+result); }else { //发送成功,把验证码信息保存到session VerifyCodeVo verifyCodeVo = new VerifyCodeVo(); verifyCodeVo.setPhone(phone); verifyCodeVo.setVerifyCode(verifyCode); verifyCodeVo.setLastTime(new Date()); UserContext.setVerifyCode(verifyCodeVo); } if (httpResponse != null) { httpResponse.close(); } if (httpClient != null) { httpClient.close(); } }else { //小于, 不能发送 jsonResult.setStatus(false); } return jsonResult; }