我在学习Java秒杀系统视频,遇到了关于ajax请求异步的问题(第一次用到ajax,不知道是不是这么称呼)。
其中有一个功能是输入手机号后获取验证码。下面是获取验证码页面getotp.html
<!--省略头文件等-->
<body class="login">
<div class="content">
<h3 class="form-title">获取otp信息</h3>
<div class="form-group">
<label class="control-label">手机号</label>
<div>
<input class="form-control" type="text" placeholder="手机号" name="telphone" id="telphone"/>
</div>
</div>
<div class="form-actions">
<button class="btn blue" id="getotp" type="submit">
获取otp短信
</button>
</div>
</div>
</body>
<script>
jQuery(document).ready(function(){
//绑定otp的click时间用于向后端发送获取手机验证码的请求
$("#getotp").on("click",function(){
var telphone = $("#telphone").val();
if(telphone == null || telphone == ""){
alert("手机号不能为空");
return false;
}
$.ajax({
type:"POST",
contentType:"application/x-www-form-urlencoded",
url:"http://localhost:8090/user/getotp",
data:{
"telphone":$("#telphone").val(),
},
xhrFields:{withCredentials:true},
success:function(data){
if(data.status == "success"){
alert("otp已经发送到了您的手机上,请注意查收");
window.location.href="./register.html";
}else{
alert("otp发送失败,原因为"+data.data.errMsg);
}
},
error:function(data){
alert("otp发送失败,原因为"+data.responseText);
}
});
return false;
});
});
</script>
在输入完手机号后,跳转至userController的getOtp方法。该方法在算出验证码后,将电话-验证码放入HttpServletRequest的getSession里,然后在控制台输出电话号码和验证码,最后返回状态码success,跳转至注册页面register.html,如下所示:
<body class="login">
<div class="content">
<h3 class="form-title">用户注册</h3>
<div class="form-group">
<label class="control-label">手机号</label>
<div>
<input class="form-control" type="text" placeholder="手机号" name="telphone" id="telphone"/>
</div>
</div>
<div class="form-group">
<label class="control-label">验证码</label>
<div>
<input class="form-control" type="text" placeholder="验证码" name="otpCode" id="otpCode"/>
</div>
</div>
<div class="form-group">
<label class="control-label">用户昵称</label>
<div>
<input class="form-control" type="text" placeholder="用户昵称" name="name" id="name"/>
</div>
</div>
<div class="form-group">
<label class="control-label">性别</label>
<div>
<input class="form-control" type="text" placeholder="性别" name="gender" id="gender"/>
</div>
</div>
<div class="form-group">
<label class="control-label">年龄</label>
<div>
<input class="form-control" type="text" placeholder="年龄" name="age" id="age"/>
</div>
</div>
<div class="form-group">
<label class="control-label">密码</label>
<div>
<input class="form-control" type="password" placeholder="密码" name="password" id="password"/>
</div>
</div>
<div class="form-actions">
<button class="btn blue" id="register" type="submit">
提交注册
</button>
</div>
</div>
</body>
<script>
jQuery(document).ready(function(){
//绑定otp的click时间用于向后端发送获取手机验证码的请求
$("#register").on("click",function(){
var telphone = $("#telphone").val();
var password = $("#password").val();
var age = $("#age").val();
var gender = $("#gender").val();
var name = $("#name").val();
var otpCode = $("#otpCode").val();
if(telphone == null || telphone == ""){
alert("手机号不能为空");
return false;
}
if(password == null || password == ""){
alert("密码不能为空");
return false;
}
if(age == null || age == ""){
alert("年龄不能为空");
return false;
}
if(gender == null || gender == ""){
alert("性别不能为空");
return false;
}
if(otpCode == null || otpCode == ""){
alert("密码不能为空");
return false;
}
$.ajax({
type:"POST",
contentType:"application/x-www-form-urlencoded",
url:"http://localhost:8090/user/register",
data:{
"telphone":$("#telphone").val(),
"password":password,
"age":age,
"gender":gender,
"otpCode":otpCode,
"name":name
},
xhrFields:{withCredentials:true},
success:function(data){
if(data.status == "success"){
alert("注册成功");
window.location.href="./login.html";
}else{
alert("注册失败,原因为"+data.data.errMsg);
}
},
error:function(data){
alert("注册失败,原因为"+data.responseText);
}
});
return false;
});
});
</script>
填写完后点击按钮后,发起ajax请求到UserController的register方法,该方法会先从HttpServletRequest.getSession()中取出先前在getotp方法里放入的电话-验证码键值对。
我的问题出现在这里:我可以肯定在getotp方法里是成功将电话-验证码放入session里,但在register方法中getSession()里取出电话对应的验证码是空的。
@Controller("user")
@RequestMapping("/user")
@CrossOrigin(allowCredentials="true", allowedHeaders = "*")
public class UserController extends BaseController{
@Autowired
private UserService userService;
@Autowired
private HttpServletRequest httpServletRequest;
//用户注册接口
@RequestMapping(value = "/register",method = {RequestMethod.POST},consumes={CONTENT_TYPE_FORMED})
@ResponseBody
public CommonReturnType register(@RequestParam(name="telphone")String telphone,
@RequestParam(name="otpCode")String otpCode,
@RequestParam(name="name")String name,
@RequestParam(name="gender")Integer gender,
@RequestParam(name="age")Integer age,
@RequestParam(name="password")String password) throws BusinessException, UnsupportedEncodingException, NoSuchAlgorithmException {
//验证手机号和对应的otpcode相符合
String inSessionOtpCode = (String) this.httpServletRequest.getSession().getAttribute(telphone);
if(!com.alibaba.druid.util.StringUtils.equals(otpCode,inSessionOtpCode)){
throw new BusinessException(EmBusinessError.PARAMETER_VALIDATION_ERROR,"短信验证码不符合");
}
//...此处省略
}
public String EncodeByMd5(String str) throws NoSuchAlgorithmException, UnsupportedEncodingException {
//确定计算方法
MessageDigest md5 = MessageDigest.getInstance("MD5");
BASE64Encoder base64en = new BASE64Encoder();
//加密字符串
String newstr = base64en.encode(md5.digest(str.getBytes("utf-8")));
return newstr;
}
//用户获取otp短信接口
@RequestMapping(value = "/getotp",method = {RequestMethod.POST},consumes={CONTENT_TYPE_FORMED})
@ResponseBody
public CommonReturnType getOtp(@RequestParam(name="telphone")String telphone){
//需要按照一定的规则生成OTP验证码
Random random = new Random();
int randomInt = random.nextInt(99999);
randomInt += 10000;
String otpCode = String.valueOf(randomInt);
//将OTP验证码同对应用户的手机号关联,使用httpsession的方式绑定他的手机号与OTPCODE
httpServletRequest.getSession().setAttribute(telphone,otpCode);
//将OTP验证码通过短信通道发送给用户,省略
System.out.println("telphone = " + telphone + " & otpCode = "+otpCode);
return CommonReturnType.create(null);
}
在视频里老师说这是异步请求的问题导致session里取不到值,可以通过在controller里添加
@CrossOrigin(allowCredentials="true", allowedHeaders = "*")
注解以及在页面里的ajax请求里添加
xhrFields:{withCredentials:true}
就可以解决,但我在这里运行老师给的代码并没解决此问题。
此外如果页面所在的文件夹是放在项目文件夹里,则不会出现session取不到验证码的问题,但如果页面所在文件夹是独立放在项目文件夹以外的地方,就会出现这个问题。
请教一下我该怎么做?
Springboot版本为2.0.5