使用Spring Boot完成邮箱登录注册
源码:https://github.com/Hobo-clh/spring-boot-email
前提
主要记录一下邮箱注册,使用Spring Boot和MyBatis
- springboot中导入email相关依赖
- 开启邮箱的POP3/SMTP服务(这里使用的是qq邮箱)文档
- 在springboot的配置文件中添加email相关配置
编码思路
- 获取验证码:填写邮箱号后点击发送验证码按钮–>发送ajax请求–>后端生成验证码发送邮件,生成一个验证对象插入验证表中,使用多线程五分钟后删除改信息。
- 注册: 点击注册按钮–>发送ajax请求–>后端判断验证码是否正确–>返回json数据–>注册是否成功
开始
目录结构
在idea中创建Spring Boot工程
在pom.xml 配置文件中加入spring-boot-starter-mail 依赖1
2
3
4<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>在springboot配置文件application.yml中添加邮箱配置信息
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17#邮件相关配置
spring:
mail:
host: smtp.qq.com
username: longhuahobo@foxmail.com
password: qq邮箱是授权码
port: 465
# SMTP服务
properties:
mail:
smtp:
ssl:
enable: true
auth: true
socketFactory:
class: javax.net.ssl.SSLSocketFactory
port: 465model层User和Verify实体类,数据库创建相对应的表
1
2
3
4
5
6
7
8
9
10
11package com.example.springboot.model;
import lombok.Data;
/**
* 用户表
*/
public class User {
private Long id;
private String email;
private String password;
}1
2
3
4
5
6
7
8
9
10package com.example.springboot.model;
import lombok.Data;
/**
* 临时验证码存放表
*/
public class Verify {
private Long id;
private String email;
private int code;
}当进行注册的业务逻辑时,会出现一些错误信息,例如邮箱号为空、验证码为空等,要将这些信息精准的返回给用户则需要添加一个enum类,对这些错误信息进行定义
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27package com.example.springboot.exception;
/**
* 自定义枚举类,将错误信息定义为枚举
*/
public enum CustomizeErrorCode {
EMAIL_IS_EXIST(201,"邮箱已经注册过了"),
EMAIL_IS_BLANK(202,"邮箱不能为空"),
EMAIL_OR_PWD_BLANK(203,"邮箱或密码不能为空"),
INVALID_ADDRESSES(204,"无效的地址!"),
VERIFY_IS_ERROR(205,"验证码错误"),
REGISTER_FAIL(206,"注册失败"),
EMAIL_OR_PWD_ERROR(206,"邮箱号或密码错误,登录失败");
private Integer code;
private String message;
public String getMessage() {
return message;
}
public Integer getCode() {
return code;
}
CustomizeErrorCode(Integer code,String message) {
this.message = message;
this.code = code;
}
}将错误信息封装到dto层的ResuDTO中
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36package com.example.springboot.dto;
import com.example.springboot.exception.CustomizeErrorCode;
import lombok.Data;
/**
* 返回工具类
*/
public class ResultDTO {
private Integer code;
private String message;
/**
* 将CustomizeErrorCode枚举对象的值转换给ResultDTO
* @param errorCode 枚举对象
* @return
*/
public static ResultDTO errorInfo(CustomizeErrorCode errorCode){
return init(errorCode.getCode(),errorCode.getMessage());
}
/**
* 初始化ResultDTO对象
* @param code 状态码
* @param message 描述信息
* @return
*/
private static ResultDTO init(Integer code,String message){
ResultDTO resultDTO = new ResultDTO();
resultDTO.setCode(code);
resultDTO.setMessage(message);
return resultDTO;
}
public static ResultDTO info(Integer code, String message) {
return init(code,message);
}
}controller层的RegisterController
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53package com.example.springboot.controller;
import com.example.springboot.dto.ResultDTO;
import com.example.springboot.dto.UserDTO;
import com.example.springboot.exception.CustomizeErrorCode;
import com.example.springboot.service.RegisterService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
public class registerController {
RegisterService registerService;
JavaMailSender mailSender;
/**
* 注册
* 将注册参数code、email、pwd封装带UserDTO中
* @param userDTO
* @return ResultDTO 返回json格式,带有code和message
*/
"/register") (
public ResultDTO register(UserDTO userDTO){
System.out.println(userDTO);
if (StringUtils.isBlank(userDTO.getEmail())&&StringUtils.isBlank(userDTO.getPassword())){
return ResultDTO.errorInfo(CustomizeErrorCode.EMAIL_OR_PWD_BLANK);
}
return registerService.register(userDTO);
}
/**
* 发送验证码
* @param email 邮箱号
* @return ResultDTO 返回json格式,带有code和message
*/
"/sendCode") (
public ResultDTO sendCode(@RequestParam("email") String email){
System.out.println(email);
if (StringUtils.isBlank(email)){
return ResultDTO.errorInfo(CustomizeErrorCode.EMAIL_IS_BLANK);
}
ResultDTO resultDTO = registerService.sendCode(email);
if (resultDTO.getCode()==200) {
//多线程五分钟后删除
registerService.removeCode(email);
}
return resultDTO;
}
}service层的RegisterService,创建多线程将发送的验证码在5分钟后进行删除(使用“@Async”时需要在Spring Boot启动类使用“@EnableAsync”)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116package com.example.springboot.service;
import com.example.springboot.dto.ResultDTO;
import com.example.springboot.dto.UserDTO;
import com.example.springboot.exception.CustomizeErrorCode;
import com.example.springboot.mapper.UserMapper;
import com.example.springboot.mapper.VerifyMapper;
import com.example.springboot.model.User;
import com.example.springboot.model.Verify;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.MailException;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
4j
public class RegisterService {
UserMapper userMapper;
JavaMailSender mailSender;
VerifyMapper verifyMapper;
/**
* 检查邮箱号是否注册
* @param email 邮箱号
* @return
*/
public boolean checkRegister(String email){
User user1 = userMapper.selectByEmail(email);
if (user1==null){
return true;
}
return false;
}
/**
* 注册
* @param userDTO 该对象参数含有email、pwd、code
* @return ResultDTO
*/
public ResultDTO register(UserDTO userDTO) {
//checkRegister()返回结果为true表示可以注册
if (!checkRegister(userDTO.getEmail())){
return ResultDTO.errorInfo(CustomizeErrorCode.EMAIL_IS_EXIST);
}
userDTO.getCode();
Verify verify = verifyMapper.selectVerify(userDTO.getCode(),userDTO.getEmail());
if (verify==null){
//验证码错误
return ResultDTO.errorInfo(CustomizeErrorCode.VERIFY_IS_ERROR);
}
User user = new User();
user.setEmail(userDTO.getEmail());
user.setPassword(userDTO.getPassword());
int flag = userMapper.insert(user);
//注册成功
if (flag==1){
//登录成功将验证码删除
verifyMapper.deleteByEmail(userDTO.getEmail());
return ResultDTO.info(200,"注册成功");
}
//注册失败
return ResultDTO.errorInfo(CustomizeErrorCode.REGISTER_FAIL);
}
/**
* 发送邮件
* @param email 邮箱号
* @return ResultDTO
*/
public ResultDTO sendCode(String email){
//随机六位数验证码
if (!checkRegister(email)){
return ResultDTO.errorInfo(CustomizeErrorCode.EMAIL_IS_EXIST);
}
try {
SimpleMailMessage message = new SimpleMailMessage();
int code = (int)((Math.random() * 9 + 1) * 100000);
message.setSubject("Hobo社区验证码");
message.setText("欢迎加入Hobo社区! 您的验证码是:"+ code + ",请在5分钟内完成注册。");
message.setTo(email);
message.setFrom("longhuahobo@foxmail.com");
mailSender.send(message);
Verify verify = new Verify();
//
verify.setCode(code);
verify.setEmail(email);
verifyMapper.insert(verify);
return ResultDTO.info(200,"邮件发送成功");
}catch (MailException e){
log.error("邮件发送出错" + e);
return ResultDTO.errorInfo(CustomizeErrorCode.INVALID_ADDRESSES);
}
}
/**
* 使用多线程五分钟后清除验证码数据
* @param email email
*/
public void removeCode(String email){
try {
Thread.sleep(1000*60*5);
verifyMapper.deleteByEmail(email);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}mapper层的UserMapper、VerifyMapper,使用注解方式对数据库进行增删改查
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42package com.example.springboot.mapper;
import com.example.springboot.model.User;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
public interface UserMapper {
/**
* 插入用户表
* @param user 用户,带有email、password参数
* @return
*/
"insert into user(email,password) values(#{email},#{password})") (
int insert(User user);
/**
* 使用id查找用户
* @param id 用户id
* @return
*/
"select * from user where id = #{id}") (
User selectById(Long id);
/**
* 使用邮箱号和密码查找用户
* @param email 邮箱号
* @param password 密码
* @return
*/
"select * from user where email = #{email} and password = #{password} ") (
User selectByEmailPwd(String email, String password);
/**
* 使用邮箱号查找用户
* @param email 邮箱号
* @return
*/
"select * from user where email = #{email}") (
User selectByEmail(String email);
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35package com.example.springboot.mapper;
import com.example.springboot.model.Verify;
import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
public interface VerifyMapper {
/**
* 插入验证表
* @param verify 带有email和code参数
* @return
*/
"insert into verify(email,code) values(#{email},#{code})") (
int insert(Verify verify);
/**
* 使用验证码和邮箱号查找验证表
* @param code 验证码
* @param email 邮箱号
* @return
*/
"select * from verify where code = #{code} and email = #{email}") (
Verify selectVerify(String code,String email);
/**
* 使用邮箱号删除验证表
* @param email 邮箱号
* @return
*/
"delete from verify where email = #{email}") (
int deleteByEmail(String email);
}前端代码省略….
结束
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Hobo's blog!
评论