<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.0modelVersion>
<parent>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-parentartifactId>
<version>2.7.3version>
<relativePath/>
parent>
<groupId>com.singroupId>
<artifactId>RedisMailMessageartifactId>
<version>0.0.1-SNAPSHOTversion>
<packaging>warpackaging>
<name>RedisMailMessagename>
<description>RedisMailMessagedescription>
<properties>
<java.version>17java.version>
properties>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-mailartifactId>
dependency>
<dependency>
<groupId>org.mybatis.spring.bootgroupId>
<artifactId>mybatis-spring-boot-starterartifactId>
<version>2.3.1version>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-data-redisartifactId>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-actuatorartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starterartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-thymeleafartifactId>
dependency>
<dependency>
<groupId>org.apache.commonsgroupId>
<artifactId>commons-lang3artifactId>
<version>3.5version>
dependency>
dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-maven-pluginartifactId>
plugin>
<plugin>
<groupId>org.apache.maven.pluginsgroupId>
<artifactId>maven-surefire-pluginartifactId>
<version>2.22.2version>
<configuration>
<skipTests>trueskipTests>
configuration>
plugin>
plugins>
build>
project>
spring:
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/demo
username: root
password: 123456
redis:
# 地址
host: 192.168.226.137
# 端口
port: 6379
# 密码
password: 123456
# 超时时间 5000毫秒
timeout: 5000
jedis:
# 连接池
pool:
# 连接池最小空闲连接
min-idle: 0
# 连接池的最大空闲连接
max-idle: 8
# 连接池最大阻塞等待时间(使用负数表示没有限制)
max-wait: -1
# 连接池最大连接数(使用负数表示没有限制)
max-active: 8
mail:
# 配置SMTP服务器地址
host: smtp.126.com
# 配置端口号465或者25
port: 25
# 发送者邮箱(根据自己邮箱填写)
username: [email protected]
# 配置密码,注意是开启POP3/SMTP的授权密码(根据自己的授权密码填写)
password: RVJJ****NTPUEHO
properties:
mail:
smtp:
auth: true
enable: true
ssl:
# 设为true时 端口号设为 465 设为false时 端口号设为25
enable: false
socketFactoryClass: 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.pojo
configuration:
# 开启驼峰命名
map-underscore-to-camel-case: true
logging:
level:
org.mybatis: debug
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='[email protected]';
insert into user_email(name,password,email,code_status) value ('admin','123456','[email protected]',1);
select * from user_email where name = 'admin' and password = '123456' and code_status = 1;
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;
}
@Override
public String toString() {
return "UserEmail{" +
"id=" + id +
", name='" + name + '\'' +
", password='" + password + '\'' +
", email='" + email + '\'' +
", codeStatus='" + codeStatus + '\'' +
'}';
}
}
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);
}
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 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>
<select id="findAllByEmail" resultMap="UserMap">
select * from user_email where email = #{email} and code_status = 1
select>
<select id="findByEmail" parameterType="string" resultMap="UserMap">
select * from user_email where email = #{email} and code_status = 2
select>
mapper>
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);
}
}
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);
}
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 {
@Autowired
private UserEmailMapper userEmailMapper;
@Autowired
private EmailService emailService;
@Override
public 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(),"验证码","+userEmail.getEmail()+"\">激活请点击:");
return userEmailMapper.insertUserEmail(userEmail);
}
}
@Override
public UserEmail findAllByEmail(String email) {
return userEmailMapper.findAllByEmail(email);
}
@Override
public String sendCode(String email) throws MessagingException {
UserEmail allByEmail = this.findAllByEmail(new UserEmail().getEmail());
return "";
}
@Override
public Object getCode(String email) {
if (email != null){
Object o = redisUtil.get(email);
System.out.println(o);
return o;
}else {
return "未填写邮箱";
}
}
@Override
public void updateCodeStatus(String email) {
userEmailMapper.updateCodeStatus(email);
}
@Override
public boolean loginUser(String email, String password) {
UserEmail userByName = userEmailMapper.findByEmail(email);
return userByName != null && userByName.getPassword().equals(password);
}
@Override
public UserEmail findUserByName(String userEmail) {
return null;
}
@Override
public List<UserEmail> seletctUserEmail() {
return userEmailMapper.seletctUserEmail();
}
}
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 {
@Autowired
private 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}")
@ResponseBody
public 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";
}
}
}
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}">
<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>
<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>
邮箱