文章目录
- SpringBoot+网易邮箱登录注册
- pom.xml
- application.yml
- sql
- UserEmail.java
- UserEmailMapper.java
- UserEmailMapper.xml
- EmailService.java
- UserEmailService.java
- UserEmailServiceImpl.java
- UserEmailController.java
- register1.html
编写前参考
SpringBoot+网易邮箱登录注册
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.7.3</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.sin</groupId><artifactId>RedisMailMessage</artifactId><version>0.0.1-SNAPSHOT</version><packaging>war</packaging><name>RedisMailMessage</name><description>RedisMailMessage</description><properties><java.version>17</java.version></properties><dependencies><!--邮箱业务:用于操作邮件功能的--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-mail</artifactId></dependency><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.3.1</version></dependency><!-- redis --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><!--对SpringBoot应用的监控--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!--SpringBoot框架的启动器--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency><!--SpringBoot框架的测试库--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId></dependency><!-- Java提供的工具库 --><dependency><groupId>org.apache.commons</groupId><artifactId>commons-lang3</artifactId><version>3.5</version></dependency></dependencies><build><plugins><!--SpringBoot应用打包为可执行的jar文件--><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin><!--单元测试的插件配置为逃过运行测试--><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-surefire-plugin</artifactId><version>2.22.2</version><configuration><skipTests>true</skipTests></configuration></plugin></plugins></build></project>
application.yml
spring:datasource:driver-class-name: com.mysql.jdbc.Driverurl: jdbc:mysql://localhost:3306/demousername: rootpassword: 123456redis:# 地址host: 192.168.226.137# 端口port: 6379# 密码password: 123456# 超时时间 5000毫秒timeout: 5000jedis:# 连接池pool:# 连接池最小空闲连接min-idle: 0# 连接池的最大空闲连接max-idle: 8# 连接池最大阻塞等待时间(使用负数表示没有限制)max-wait: -1# 连接池最大连接数(使用负数表示没有限制)max-active: 8mail:# 配置SMTP服务器地址host: smtp.126.com# 配置端口号465或者25port: 25# 发送者邮箱(根据自己邮箱填写)username: sin8023@126.com# 配置密码,注意是开启POP3/SMTP的授权密码(根据自己的授权密码填写)password: RVJJ****NTPUEHOproperties:mail:smtp:auth: trueenable: truessl:# 设为true时 端口号设为 465 设为false时 端口号设为25enable: falsesocketFactoryClass: javax.net.ssl.SSLSocketFactory#表示开启 DEBUG 模式,这样,邮件发送过程的日志会在控制台打印出来,方便排查错误debug: true# 邮箱编码格式default-encoding: UTF-8
# thymeleaf:
# prefix: classpath:/templates/
# suffix: .html
# mode: HTML
# encoding: utf-8
# servlet.content-type: text/html
# check-template-location: true #检查模板路径是否存在
# cache: false# mybatis配置
mybatis:# 获取配置文件的地址mapper-locations: classpath:/mapper/*.xml# 获取实体类的地址type-aliases-package: com.sin.pojoconfiguration:# 开启驼峰命名map-underscore-to-camel-case: truelogging:level:org.mybatis: debug
sql
create table user_email
(id int auto_increment primary key comment '主键id',name varchar(20) character set utf8mb4 not null comment '用户名',password varchar(20) character set utf8mb4 not null comment '密码',email varchar(20) character set utf8mb4 not null comment '邮箱',code_status int default 0 comment '邮箱验证状态 1 = 未注册 ,1 = 已经注册 其余数字为无效标识符'
)charset = utf8mb4;insert into user_email(name,password,email,code_status) select email,'aaa' from user where email='123@qq.com';insert into user_email(name,password,email,code_status) value ('admin','123456','123@qq.com',1);select * from user_email where name = 'admin' and password = '123456' and code_status = 1;
UserEmail.java
package com.sin.pojo;public class UserEmail {private long id;private String name;private String password;private String email;private int codeStatus;public UserEmail() {}public UserEmail(String name, String password, String email) {this.name = name;this.password = password;this.email = email;}public long getId() {return id;}public void setId(long id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}public String getEmail() {return email;}public void setEmail(String email) {this.email = email;}public int getCode_status() {return codeStatus;}public void setCode_status(int codeStatus) {this.codeStatus = codeStatus;}@Overridepublic String toString() {return "UserEmail{" +"id=" + id +", name='" + name + '\'' +", password='" + password + '\'' +", email='" + email + '\'' +", codeStatus='" + codeStatus + '\'' +'}';}
}
UserEmailMapper.java
package com.sin.mapper;import com.sin.pojo.UserEmail;
import org.apache.ibatis.annotations.Mapper;import java.util.List;/*** @createTime 2023/10/23 15:39* @createAuthor SIN* @use 数据访问层,数据访问的核心任务*/
@Mapper
public interface UserEmailMapper {/*** 添加数据* @param userEmail* @return*/int insertUserEmail(UserEmail userEmail);/*** 根据用户名进行查找数据* @param userEmail* @return*/UserEmail findUserByName(String userEmail);/*** 查询所有数据* @return*/List<UserEmail> seletctUserEmail();/*** 根据邮箱进行查询* @param email* @return*/UserEmail findAllByEmail(String email);/*** 更新数据* @param email* @return*/void updateCodeStatus(String email);/*** 根据邮箱查询数据* @param email* @return*/UserEmail findByEmail(String email);
}
UserEmailMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.sin.mapper.UserEmailMapper"><!--resultMap通过将查询结果集中的列名和Java对象中的属性名进行映射,实现了结果集的自动映射。同时,它还可以解决列名和属性名不匹配的问题,支持复杂类型映射,提高了查询性能。--><resultMap id="UserMap" type="com.sin.pojo.UserEmail"><id property="id" column="id"/><result property="name" column="name"/><result property="password" column="password"/><result property="email" column="email"/><result property="codeStatus" column="code_status"/></resultMap><!-- 添加数据 --><insert id="insertUserEmail" parameterType="com.sin.pojo.UserEmail">insert into user_email(name,password,email,code_status)values (#{name},#{password},#{email},#{codeStatus})</insert><update id="updateCodeStatus" parameterType="com.sin.pojo.UserEmail">update user_email set code_status = 2 where email = #{email};</update><!-- 根据姓名密码查询数据 --><select id="findUserByName" resultMap="UserMap">select name from user where name = #{name} and password = #{password} and code_status = 1</select><!-- 查询所有数据 --><select id="seletctUserEmail" resultMap="UserMap">select * from user_email</select><!-- code_status = 1时,表明用户已经存在但未完成注册操作 --><select id="findAllByEmail" resultMap="UserMap">select * from user_email where email = #{email} and code_status = 1</select><!-- code_status = 2时,表明用户已经完成注册操作可以进行登录操作 --><select id="findByEmail" parameterType="string" resultMap="UserMap">select * from user_email where email = #{email} and code_status = 2</select></mapper>
EmailService.java
package com.sin.service;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Service;import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;/*** @createTime 2023/11/21 10:18* @createAuthor SIN* @use*/@Service
public class EmailService {@Autowired(required = false)private JavaMailSender mailSender;@Value("${spring.mail.username}")private String userName;/*** 发送信息邮件* @param to 收件人* @param subject 邮箱标题* @param content 邮箱内容*/public void sendMail(String to, String subject, String content) throws MessagingException {MimeMessage message = mailSender.createMimeMessage();MimeMessageHelper helper = new MimeMessageHelper(message, true);//邮箱发送者helper.setFrom(userName);//收件人,可以为多个收件人,收件人之间用逗号隔开helper.setTo(to);// 邮箱标题helper.setSubject(subject);// 邮箱内容helper.setText(content, true);mailSender.send(message);}
}
UserEmailService.java
package com.sin.service;import com.sin.exception.EmailAlreadyExistsException;
import com.sin.pojo.UserEmail;import javax.mail.MessagingException;
import java.util.List;/*** @createTime 2023/11/20 17:25* @createAuthor SIN* @use*/
public interface UserEmailService {/*** 添加数据* @param userEmail* @return*/int insertUserEmail(UserEmail userEmail) throws MessagingException, EmailAlreadyExistsException;/*** 根据用户名进行查找数据* @param userEmail* @return*/UserEmail findUserByName(String userEmail);/*** 查询所有数据* @return*/List<UserEmail> seletctUserEmail();/*** 根据邮箱进行查询* @param email* @return*/UserEmail findAllByEmail(String email);/*** 发送验证码* @return*/String sendCode(String email) throws MessagingException;/*** 获取验证码* @return*/Object getCode(String email);/*** 更新数据* @param email* @return*/void updateCodeStatus(String email);/*** 根据邮箱查询数据* @return*/boolean loginUser(String email, String password);}
UserEmailServiceImpl.java
package com.sin.service.impl;import com.sin.mapper.UserEmailMapper;
import com.sin.pojo.UserEmail;
import com.sin.exception.EmailAlreadyExistsException;
import com.sin.service.EmailService;
import com.sin.service.UserEmailService;
import com.sin.utils.RandomCodeUtil;
import com.sin.utils.RedisUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import javax.mail.MessagingException;
import java.util.List;/*** @createTime 2023/11/20 17:25* @createAuthor SIN* @use*/
@Service
public class UserEmailServiceImpl implements UserEmailService {@Autowiredprivate UserEmailMapper userEmailMapper;@Autowiredprivate EmailService emailService;@Overridepublic int insertUserEmail(UserEmail userEmail) throws MessagingException, EmailAlreadyExistsException {// 1,查询要添加的数据如果没有数据就添加UserEmail allByEmail = this.findAllByEmail(userEmail.getEmail());if (allByEmail != null){throw new EmailAlreadyExistsException("该邮箱以注册,请登录");}else {System.out.println("数据添加成功");userEmail.setCode_status(1);emailService.sendMail(userEmail.getEmail(),"验证码","<a href=\"http://localhost:8080/update/"+userEmail.getEmail()+"\">激活请点击:</a>");return userEmailMapper.insertUserEmail(userEmail);}}@Overridepublic UserEmail findAllByEmail(String email) {return userEmailMapper.findAllByEmail(email);}@Overridepublic String sendCode(String email) throws MessagingException {UserEmail allByEmail = this.findAllByEmail(new UserEmail().getEmail());return "";}@Overridepublic Object getCode(String email) {if (email != null){Object o = redisUtil.get(email);System.out.println(o);return o;}else {return "未填写邮箱";}}@Overridepublic void updateCodeStatus(String email) {userEmailMapper.updateCodeStatus(email);}@Overridepublic boolean loginUser(String email, String password) {UserEmail userByName = userEmailMapper.findByEmail(email);return userByName != null && userByName.getPassword().equals(password);}@Overridepublic UserEmail findUserByName(String userEmail) {return null;}@Overridepublic List<UserEmail> seletctUserEmail() {return userEmailMapper.seletctUserEmail();}}
UserEmailController.java
package com.sin.controller;import com.sin.exception.EmailAlreadyExistsException;
import com.sin.mapper.UserEmailMapper;
import com.sin.pojo.UserEmail;
import com.sin.service.UserEmailService;
import org.apache.catalina.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;import javax.mail.MessagingException;/*** @createTime 2023/11/22 11:47* @createAuthor SIN* @use*/
@Controller
public class UserEmailController {@Autowiredprivate UserEmailService userEmailService;@GetMapping("/register")public String login(Model model){UserEmail userEmail = new UserEmail();model.addAttribute("userEmail",userEmail);// 设置成功消息model.addAttribute("successMessage", "邮件已发送,请注意查收");return "register1";}@PostMapping("/register")// @ModelAttribut : 将请求参数绑定到模型对象上,public String login(@ModelAttribute("userEmail") UserEmail userEmail, Model model) throws MessagingException {try{int result = userEmailService.insertUserEmail(userEmail); // 执行用户注册System.out.println(result);}catch (EmailAlreadyExistsException e){String errorMessage = e.getMessage();System.out.println(errorMessage);model.addAttribute("errorMessage",errorMessage);}return "redirect:/register";}@GetMapping("/update/{email}")@ResponseBodypublic String updateCodeStatus(@PathVariable("email") String email){userEmailService.updateCodeStatus(email);return "SUCCESS";}@PostMapping("/login")public String loginUser(@RequestParam("email") String email, @RequestParam("password") String password) {boolean isValid = userEmailService.loginUser(email, password);System.out.println(isValid);// 登录成功后返回到/dashboard页面if (isValid) {return "SUCCESS";} else { // 登录失败返回该页面return "login";}}}
register1.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>登录/注册</title><style>:root {/* COLORS */--white: #e9e9e9;--gray: #333;--blue: #0367a6;--lightblue: #008997;/* RADII */--button-radius: 0.7rem;/* SIZES */--max-width: 758px;--max-height: 420px;font-size: 16px;font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen,Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif;}body {align-items: center;background-color: var(--white);background: url("https://res.cloudinary.com/dbhnlktrv/image/upload/v1599997626/background_oeuhe7.jpg");/* 决定背景图像的位置是在视口内固定,或者随着包含它的区块滚动。 *//* https://developer.mozilla.org/zh-CN/docs/Web/CSS/background-attachment */background-attachment: fixed;background-position: center;background-repeat: no-repeat;background-size: cover;display: grid;height: 100vh;place-items: center;}.form__title {font-weight: 300;margin: 0;margin-bottom: 1.25rem;}.link {color: var(--gray);font-size: 0.9rem;margin: 1.5rem 0;text-decoration: none;}.container {background-color: var(--white);border-radius: var(--button-radius);box-shadow: 0 0.9rem 1.7rem rgba(0, 0, 0, 0.25),0 0.7rem 0.7rem rgba(0, 0, 0, 0.22);height: var(--max-height);max-width: var(--max-width);overflow: hidden;position: relative;width: 100%;}.container__form {height: 100%;position: absolute;top: 0;transition: all 0.6s ease-in-out;}.container--signin {left: 0;width: 50%;z-index: 2;}.container.right-panel-active .container--signin {transform: translateX(100%);}.container--signup {left: 0;opacity: 0;width: 50%;z-index: 1;}.container.right-panel-active .container--signup {animation: show 0.6s;opacity: 1;transform: translateX(100%);z-index: 5;}.container__overlay {height: 100%;left: 50%;overflow: hidden;position: absolute;top: 0;transition: transform 0.6s ease-in-out;width: 50%;z-index: 100;}.container.right-panel-active .container__overlay {transform: translateX(-100%);}.overlay {background-color: var(--lightblue);background: url("https://cdn.pixabay.com/photo/2018/08/14/13/23/ocean-3605547_1280.jpg");background-attachment: fixed;background-position: center;background-repeat: no-repeat;background-size: cover;height: 100%;left: -100%;position: relative;transform: translateX(0);transition: transform 0.6s ease-in-out;width: 200%;}.container.right-panel-active .overlay {transform: translateX(50%);}.overlay__panel {align-items: center;display: flex;flex-direction: column;height: 100%;justify-content: center;position: absolute;text-align: center;top: 0;transform: translateX(0);transition: transform 0.6s ease-in-out;width: 50%;}.overlay--left {transform: translateX(-20%);}.container.right-panel-active .overlay--left {transform: translateX(0);}.overlay--right {right: 0;transform: translateX(0);}.container.right-panel-active .overlay--right {transform: translateX(20%);}.btn {background-color: var(--blue);background-image: linear-gradient(90deg, var(--blue) 0%, var(--lightblue) 74%);border-radius: 20px;border: 1px solid var(--blue);color: var(--white);cursor: pointer;font-size: 0.8rem;font-weight: bold;letter-spacing: 0.1rem;padding: 0.9rem 4rem;text-transform: uppercase;transition: transform 80ms ease-in;}.form>.btn {margin-top: 1.5rem;}.btn:active {transform: scale(0.95);}.btn:focus {outline: none;}.form {background-color: var(--white);display: flex;align-items: center;justify-content: center;flex-direction: column;padding: 0 3rem;height: 100%;text-align: center;}.input {background-color: #fff;border: none;padding: 0.9rem 0.9rem;margin: 0.5rem 0;width: 100%;}@keyframes show {0%,49.99% {opacity: 0;z-index: 1;}50%,100% {opacity: 1;z-index: 5;}}.error-message{color: red;}</style>
</head><body>
<div class="container right-panel-active"><!-- 注册 --><div class="container__form container--signup"><form method="post" th:action="@{/register}" th:object="${userEmail}" class="form" id="form1"><h2 class="form__title">注册</h2><input type="text" placeholder="用户" th:field="*{name}" class="input" /><input type="password" placeholder="密码" th:field="*{password}" class="input" /><input type="email" placeholder="邮箱" th:field="*{email}" class="input" /><div class="error-message" th:if="${errorMessage}"> <!-- 修改变量名为 "errorMessage" --><p id = "aaa" th:text="${errorMessage}"></p></div><button class="btn" type="submit">注册</button></form></div><div class="success-message" th:if="${successMessage}"><p th:text="${successMessage}"></p></div><!-- 登录 --><div class="container__form container--signin"><form method="post" th:action="@{/login}" class="form" id="form2"><h2 class="form__title">登录</h2><input type="email" placeholder="Email" name="email" class="input" /><input type="password" placeholder="Password" name="password" class="input" /><a href="#" class="link">忘记密码了?</a><button class="btn" type="submit" >注册</button></form></div><!-- Overlay --><div class="container__overlay"><div class="overlay"><div class="overlay__panel overlay--left"><button class="btn" id="signIn">登录</button></div><div class="overlay__panel overlay--right"><button class="btn" id="signUp">注册</button></div></div></div>
</div><script>const signInBtn = document.getElementById("signIn");const signUpBtn = document.getElementById("signUp");const container = document.querySelector(".container");signInBtn.addEventListener("click", () => {container.classList.remove("right-panel-active");});signUpBtn.addEventListener("click", () => {container.classList.add("right-panel-active");});// 获取页面元素const form = document.getElementById("form1");const errorMessage = document.getElementById("errorMessage");// 提交表单时,禁用按钮并显示加载状态form.addEventListener("submit", function() {const button = form.querySelector("button[type=submit]");button.disabled = true;button.innerText = "加载中...";});// 如果页面存在错误消息,则弹出消息框if (errorMessage) {alert(errorMessage.innerText);}</script>
</body></html>
邮箱