上一篇文章:基于Spring Boot实现邮箱获取验证码进行注册(链接:点击跳转)
之前那篇博客留了一点坑没填,这篇换了前端js框架来解决一些坑点
div的id是实体化的Vue对象绑定的参数
如下方的div的id为app,那么如果Vue对象要控制这个div里的内容,那么Vue对象的el值就要填这个div的id:app
<div id="app"></div>
v-model和双大括号里面加的参数是与Vue里的data里面双向绑定的,即改变一边的值,另一边的值也会同步改变
input里的v-model绑定的是input里的值,即input标签里面输入的值
双大括号则就是整块会表示为Vue里data里同名参数的值
<input style="left:20%;" v-model="password" name="{{state}}" type="password" placeholder="请输入密码">
@input方法会监听输入框里的输入,只要里面输入的值发生变化都会触发
<input style="left:20%;" v-model="userName" name="userName" type="email" placeholder="请输入邮箱" @input="check">
axios.post是请求方式,第一个参数填后端的接口(映射),第二个就是转为JOSN,然后大括号里的内容就是要传给后端的参数,会以键值对的形式返回后端,所以可以用Map来接受
然后then里面的参数就是后端返回的参数,如果不知道里面的值是怎么样的,那么可以console.log输出试试
axios.post("http://localhost:8080/Register/register",JSON.stringify({
userName: this.userName
}).then(data){
}
img标签的src前面加上v-bind就可以绑定该图片的路径,我这里用的是睁眼和闭眼的图片(可以自己去找图片),表示显示和隐藏密码。input标签绑定type直接在type前面加上冒号,然后里面值填的是与下面data里面绑定的值,如这里填的是state;
<img style="position: absolute;left:14.2%;top:5%;" v-bind:src="Info" height="20" width="20" @click="change"/>
<input style="left:20%;" v-model="password" :type="state" placeholder="请输入密码">
上面的点击图片会触发下面的方法,下面的方法会修改图片的路径以及input标签的type;
change:function(){
let _this = this
if(_this.Info==="image/close.png"){
_this.Info="image/open.png"
_this.state="text"
}else{
_this.Info="image/close.png"
_this.state="password"
}
}
Vue对象的data里面填的就是与前面html里面绑定的对象的初始值,初始没有要求的话为空字符串即可
data:{
userName:""
},
methods里面填的就是就是js的方法,可以被@click,@input等事件触发,然后使用post返回数据给控制器处理
methods: {
check: function(){
alert("这是一个方法")
}
}
前端可以在注册成功后通过控制器进行页面跳转
window.location.href = "/goto/login"
下面是用Vue.js重构的完整前端代码,
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/html" xmlns:v-on="http://www.w3.org/1999/xhtml"
xmlns:v-model="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<div>
<p style="position:absolute;left: 45%;">注册页面</p>
<div style="width: 100%;height: 2rem;position: absolute;top:10%;left: 40%;">
邮箱:
<input style="left:20%;" v-model="userName" name="userName" type="email" placeholder="请输入邮箱" @input="check">
<span>{{display}}</span>
</div>
<div style="width: 100%;height: 2rem;position: absolute;top:15%;left: 40%;">
密码:
<input style="left:20%;" v-model="password" :type="state" placeholder="请输入密码"></br>
<img style="position: absolute;left:14.2%;top:5%;" v-bind:src="Info" height="20" width="20" @click="change"/>
然后是获取验证码的控制器,与ajax作为前端js的不同的是方法接受的传参要以Map接受,同时Map前要加上@RequestBody
注解,这里对使用者的很多行为进行了限制,要注意邮箱格式一定要合法,每次发送验证码,验证码的有效期只有300s,同时在验证码的有效期内,限制用户不能再次获取验证码,同时判断该用户的用户名是否已经存在,当然,这点在前端已经有做了,但是只靠前端明显是不够的
package com.example.demo.controller;
import com.example.demo.mapper.UserMapper;
import com.example.demo.pojo.Regular;
import com.example.demo.pojo.SendMail;
import com.example.demo.pojo.User;
import com.example.demo.pojo.UserExample;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.Map;
@RestController
@RequestMapping("/GetCodeController")
public class GetCodeController {
@Resource
private UserMapper userMapper;
@Autowired
private SendMail sendMail;
//获取验证码
@RequestMapping("/getCodeController")
public String getCodeController(@RequestBody Map<String,String>user, HttpServletRequest request){
try{
if(request.getSession().getAttribute(user.get("userName"))!=null){
return "repeat";
}
}catch (Exception e){
e.printStackTrace();
return "fail";
}
//生成验证码
System.out.println(user.get("userName"));
int code=(int)((Math.random()*9+1)*100000);
if(!Regular.isEmail(user.get("userName"))||!Regular.isEmoji(user.get("userName")))return "fail";
try{
UserExample userExample=new UserExample();
userExample.createCriteria().andUserNameEqualTo(user.get("userName"));
List<User>userList=userMapper.selectByExample(userExample);
int len=userList.size();
for(int i=0;i<len;i++){
if(userList.get(i).getUserName().compareTo(user.get("userName"))==0){
return "same";
}
}
}catch (Exception e){
e.printStackTrace();
return "fail";
}
try{
//对象创建session
//通过键值对存储
request.getSession().setAttribute(user.get("userName"),code);//把验证码与该用户邮箱绑定
request.getSession().setMaxInactiveInterval(300);//自动销毁session
System.out.println(code);
sendMail.sendMail(user.get("userName"),String.valueOf(code));//给该用户发送验证码
return "success";
}catch (Exception e){
e.printStackTrace();
return "fail";
}
}
}
下面是实时检测用户名是否存在的控制器,返回的结果会在前端直接显示
package com.example.demo.controller;
import com.example.demo.mapper.UserMapper;
import com.example.demo.pojo.User;
import com.example.demo.pojo.UserExample;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
@Controller //表示该类为控制器
@RequestMapping("/CheckUserName")//映射,访问test将会被该类处理
public class CheckUserName {
@Resource
private UserMapper userMapper;
@RequestMapping("/checkUserName")
@ResponseBody
public String checkUserName(@RequestBody Map<String,String>map){
System.out.println(map.get("userName"));
try{
String userName=map.get("userName");
if(!Regular.isEmoji(userName)||!Regular.isEmail(userName))return "Error";
UserExample userExample=new UserExample();
userExample.createCriteria().andUserNameEqualTo(userName);
List<User>userList=userMapper.selectByExample(userExample);
int len=userList.size();
for(int i=0;i<len;i++){
if(userList.get(i).getUserName().compareTo(userName)==0)
return "same";
}
return "success";
}catch (Exception e){
e.printStackTrace();
return "fail";
}
}
}
下面是注册所调用的控制器,注册所要限制的可就更多了,这里限制密码要在6-16位,同时要与确认密码相同,同时会二次校验邮箱的合法性,并且因为验证码与邮箱绑定,所以更换邮箱是无法完成注册的。这里因为mysql的设计失误,所以对emoji的输入进行了限制,不同的问题会返回不同的值,在前端会对后端返回的值进行处理,只有注册成功会进行跳转到登录界面的方法
package com.example.demo.controller;
import com.example.demo.mapper.UserMapper;
import com.example.demo.pojo.Regular;
import com.example.demo.pojo.User;
import com.example.demo.pojo.UserExample;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.Map;
@Controller //表示该类为控制器
@RequestMapping("/Register")//映射,访问test将会被该类处理
public class Register {
@Resource
private UserMapper userMapper;
@RequestMapping("/register")
@ResponseBody
public String register(@RequestBody Map<String,String>map, HttpServletRequest request){
if(map.get("userName")==null||map.get("userName").length()==0||map.get("password")==null||map.get("password").length()==0||map.get("repassword")==null||map.get("repassword").length()==0)return "fail";//判空数据返回失败
UserExample userExample=new UserExample();//查询数据库里用户名是否重复,用户名不是主键这一块可以不要
userExample.createCriteria().andUserNameEqualTo(map.get("userName"));
List<User> userList=userMapper.selectByExample(userExample);
for(int i=0;i<userList.size();i++){
if(userList.get(i).getUserName().compareTo(map.get("userName"))==0){//数据库查询到已有该用户名返回失败
return "repeat";
}
}
try{
if(!Regular.isEmoji(map.get("password"))){
return "passwordError";
}
if(map.get("password").length()>16||map.get("password").length()<6){
return "low";
}
}catch (Exception e){
e.printStackTrace();
return "fail";
}
try {
if(map.get("password").compareTo(map.get("repassword"))!=0){
return "notSamePassword";
}
}catch (Exception e){
e.printStackTrace();
return "fail";
}
try {
try{
if(request.getSession().getAttribute(map.get("userName"))==null){
return "error";
}
}catch (Exception e){
e.printStackTrace();
return "error";
}
if(request.getSession().getAttribute(map.get("userName")).toString().compareTo(map.get("code"))!=0){
return "error";
}
User user=new User();
user.setUserName(map.get("userName"));
user.setUserPassword(map.get("password"));
userMapper.insert(user);
return "success";
}catch (Exception e){
e.printStackTrace();
return "fail";
}
}
}
下面是跳转页面用到的控制器,在方法前去掉@ResponseBody
注解就会使控制器在tamplates文件夹下找到同名的html文件并返回该页面
package com.example.demo.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@RequestMapping("/goto")
public class GoToPage {
@RequestMapping("/index")
public String index(){
return "index";
}
@RequestMapping("/login")
public static String login(){return "login";}
}
最后就是正则类和邮件发送类
package com.example.demo.pojo;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Regular {
public static boolean isEmoji(String email){
if (email == null)
return false;
String rule="\\uD83C[\\uDF00-\\uDFFF]|\\uD83D[\\uDC00-\\uDE4F]|\\uD83D[\\uDE80-\\uDEFF]|[\\u2700-\\u27BF]\\uFE0F";
Pattern pattern;
Matcher matcher;
pattern = Pattern.compile(rule);
matcher = pattern.matcher(email);
if (matcher.matches()){
System.out.println("Yes");
return false;
}
else
return true;
}
public static boolean isEmail(String email) {
if (email == null)
return false;
String rule = "^\\s*\\w+(?:\\.{0,1}[\\w-]+)*@[a-zA-Z0-9]+(?:[-.][a-zA-Z0-9]+)*\\.[a-zA-Z]+\\s*$";
Pattern pattern;
Matcher matcher;
pattern = Pattern.compile(rule);
matcher = pattern.matcher(email);
if (matcher.matches()){
System.out.println("Yes");
return true;
}
else
return false;
}
}
package com.example.demo.pojo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.stereotype.Component;
@Component
public class SendMail {
@Autowired
private JavaMailSender mailSender;
public void sendMail(String To,String Text)throws Exception{
try {
SimpleMailMessage messege=new SimpleMailMessage();
messege.setFrom("@qq.com");//填自己的邮箱
messege.setTo(To);
messege.setSubject("主题:测试");
messege.setText(Text);
mailSender.send(messege);
}catch (Exception e){
e.printStackTrace();
System.out.println("邮件发送失败");
}
}
}
登录页面这里没有给出,可以写一个只有注册成功的html页面进行测试