预期目的:
在重置密码页面中,用户输入账号密码点击发送验证码,假如验证码输入的情况下点击保存密码,后台返回一个错误信息给页面显示。
重置密码页面当前实现介绍:
页面使用jQuery Validate对页面字段进行验证。三个字段的验证错误信息都都使用<div id="errorMessage" class="errorMessage"></div>装载,以红色文字显示在保存按钮上方的。
重置密码页面的账号字段需要验证用户输入的账号是否存。
点击保存会把三个参数的数据传到控制层的方法,该方法的返回类型是ModelAndView。如果成功跳转回登录页面;如果失败返回重置密码页面,且ModelAndView包含错误信息等属性。
页面使用EL表达式获取控制层返回的参数值。(如果验证码错误,控制层设定mav.addObject("errorMessage", "验证码错误"); 页面使用${errorMessage}来获取信息)。
问题所在:
页面读取${errorMessage},如果非空,页面设定$("#validateForm").validate().showErrors({"validateNum":"${errorMessage}"});
可是,该验证错误信息不能一直显示,而是被账号字段的remote验证覆盖了
主要代码如下:
validate.jsp页面jQuery代码
验证定义在88行以后
<script type="text/javascript"> var InterValObj; //验证码时间变量 var count = ${count }; //间隔函数,1秒执行 var curCount;//当前剩余秒数 // 发送验证码 function getCodeVerify(){ var successNum = $("#account").valid()+$("#pw").valid(); var actionUrl = "${basePath }/rrt/user/codeVerify/getVerifyCode.do"; phoneNum = $("#account").val(); validType = $("#validType").val(); if(successNum==2 && validType!=""){ nengLongAjax({ url:actionUrl, data:{"phoneNum":phoneNum,"validType":validType}, async:false, success:function(r){ if(r.data==true || r.data=="true"){ curCount = count; //设置button效果,开始计时 $("#btnSendCode").attr("disabled", "true"); $("#btnSendCode").css({color:"#838383","background-color":"#e5e5e5"}); $("#btnSendCode").val("发送成功(" + curCount + ")"); InterValObj = window.setInterval(SetRemainTime, 1000); //启动计时器,1秒执行一次 }else{ $("#errorMessage").html(r.error); } } }) }else{ if($("#account").valid()==0 && $("#pw").valid()==0){ $("#errorMessage").html("请输入合法的账号密码"); }else if($("#pw").valid()==0){ $("#errorMessage").html("请输入合法的密码"); }else if($("#account").valid()==0){ $("#errorMessage").html("账号不合法或账号不存在"); } } } //timer处理函数 function SetRemainTime() { if (curCount == 0) { $("#errorMessage").html(""); window.clearInterval(InterValObj);//停止计时器 $("#btnSendCode").removeAttr("disabled");//启用按钮 $("#btnSendCode").val("重新发送验证码"); $("#btnSendCode").css({color:"#fff","background-color":"#15aea2"}); } else { curCount--; $("#btnSendCode").val("发送成功(" + curCount + ")"); } } // 密码显示与隐藏 function showPassword(){ var temp = $("#pw").attr("value"); if($("#pw").attr("type")=="password"){ $("#sp").html('<input type="text" class="in-pw" name="password" placeholder="输入密码" id="pw"/>'); $("#pw").attr("value",temp); }else{ $("#sp").html('<input type="password" class="in-pw" name="password" placeholder="输入密码" id="pw"/>'); $("#pw").attr("value",temp); } } $(function() { if(${validType==2}){ $("#title").html("首次使用,重置密码"); $("#button").html("保存密码"); $("#account").attr("readonly","readonly"); $("#password").show(); }else if(${validType==3 }){ $("#title").html("账号未验证,请重新激活"); $("#button").html("激活账号"); $("#account").attr("readonly","readonly"); $("#password").hide(); }else if(${validType==4}){ $("#title").html("重置密码"); $("#button").html("保存密码"); $("#password").show(); } //设置验证信息 try{ nengLongValidateSetting({ rules:{ account:{ required:true, digits:true, // 必须输入整数 rangelength:[11, 11], remote:{ url:'${basePath}/rrt/user/accountExists', type:'POST', data:{"validType":"${validType }"} } }, password:{ required:true, rangelength:[6, 32] }, validateNum:{ required:true } }, messages:{ account:{ required:"", digits:"账号只能为数字", rangelength:"账号长度11个字符", remote:"账号不存在" }, password:{ required:"", rangelength:"密码长度6~32个字符" }, validateNum:{ required:"" } }, errorPlacement:function(error, element) { $("#errorMessage").html(error); } }, "validateForm", false); <c:if test="${errorMessage!=null }"> $("#validateForm").validate().showErrors({"account":"${errorMessage}"}); </c:if> }catch(ex){ } }); </script>
控制层错误信息和账号回送到该页面后,虽然127行代码被执行,页面也能显示${errorMessage}的数据,但瞬间会调用89行中地址中的方法,使得该${errorMessage}错误信息给覆盖
validate.jsp页面表单代码
<section class="main clearfix"> <form action="${basePath }/rrt/user/validate.do" id="validateForm" method="POST" autocomplete="off"> <input type="hidden" value="${validType }" name="validType" id="validType" /> <div class="name"><input type="text" class="in-name" value="${account.account }" name="account" id="account" placeholder='输入账号' maxlength="11"/></div> <div class="password" id="password" style="display:none"> <span id="sp" class="mysp"> <input type="password" class="in-pw" value="" name="password" id="pw" placeholder='输入密码'/> </span> <a href="#" id="showPassword" onclick="showPassword();return false"></a> </div> <div class="num"> <input type="text" class="in-num" name="validateNum" id="validateNum" value="" placeholder='验证码' maxlength="6"/> <input class="btn" id="btnSendCode" type="button" value="发送验证码" onclick="getCodeVerify()" /> </div> <div id="errorMessage" class="errorMessage"></div> <div><a href="#" onclick="nengLongSubmitForm('validateForm');return false" class="sub" id="button">激活账号</a></div> </form> </section>
控制层保存密码方法:
@RequestMapping("/validate") @ResponseBody public ModelAndView validate(UserAccount userAccount, String validateNum, Integer validType){ ModelAndView mav = new ModelAndView(); TimedSystemSetting systemSetting = SystemSettingFactory.getInstance(); String oneminiTime = systemSetting.getSettings().get("oneminiTime"); try { // 判断验证码是否正确 boolean isValidate = smsCodeVerifyServiceImpl.validate(userAccount.getAccount(), validateNum, validType); if(isValidate){ //更新用户状态 UserAccount bean = accountServiceImpl.findAccount(userAccount); String newPassword = userAccount.getPassword(); if((validType==2 || validType==4) && newPassword!=null){ bean.setPassword(StringUtils.trim(AES.encoder(newPassword))); } bean.setState(1); accountServiceImpl.updateUserAccount(bean); mav.addObject("account", bean.getAccount()); mav.setViewName("user/login"); }else{ mav.addObject("count", oneminiTime); // 验证码发送间隔时间 mav.addObject("errorMessage", "验证码错误"); mav.addObject("validType", validType); mav.addObject("account", userAccount); mav.setViewName("user/validate"); } } catch (Exception e) { mav.addObject("count", oneminiTime); // 验证码发送间隔时间 mav.addObject("errorMessage", "验证码错误"); mav.addObject("account", userAccount); mav.addObject("validType", validType); mav.setViewName("user/validate"); e.printStackTrace(); } return mav; }