目录

1、前言

2、系统实机演示

3、系统分析与设计

(1)主要软件与工具

(2)系统分析

(3)系统规划

4、系统设计与构建

(1)JavaWeb创建

(2)JavaWeb运行

(3)先期依赖准备:

5、代码与关键注释、文件简析

(1)数据库

(2)前端

index.jsp和styleIndex.css:

forgetPassword.jsp和styleForgetPassword.css、sendMail.js:

mainPage.jsp和styleMainPage.css:

(3)后端(Servlet):

SignServlet.java:

EmailServlet.java:

LogoutServlet.java:

(4)后端(Util)

MailUtil.java

JDBCUtil.java

VcodeUtil.java

User.java

(5)后端(DAO)

DAO.java:

(6)配置文件

web.xml:

6、系统完成形式与参考代码


1、前言

首先,关于源码的获取,本人提供了三种方式:

  • 直接从文章里面Ctrl+C,Ctrl+V,然后按照我已给的文件结构搞一下即可;
  • 通过积分下载上传到CSDN的资源;
  • 点开本人的主页,点击“查看详细资料”,添加好友获取源码文件(如果有问题同样可以通过这里问),本人承诺无特殊情况,三小时内将无条件提供源码(所谓特殊情况仅指时间上的,毕竟挂上去的是我的副号,获取信息可能不及时,见谅)。

注:关于第二个获取方式……实际上用第三种方式就行,和第二种方式获得的文件没任何区别,再不济可以用第一种,真的真的没必要用第二种(但是做慈善的话我也欢迎,毕竟我也需要一点积分用来下载资源)

一切的一切要从我心血来潮脑子一热报了专业选修——Java说起,我承认我报的时候草率了,我承认我低估了它的难度。但是还是得写的好一点,毕竟期末结课嘛,写的好一点,多一点总归没坏处,于是就有了今天这篇改自我的实验报告和代码的JavaWeb登录注册系统。

本系统基本实现了登录注册所需的功能,包括但不限于登录检查、注册检查、多登录方式提供、邮箱验证码获取与校验等功能,还加写了一个登录后注销账户的功能。

系统总共分三个界面:

  • 第一个是负责注册和常规密码登录的界面;
  • 第二个是负责邮箱验证码登录的界面;
  • 第三个是主界面,没有实际意义,就是登陆成功后总得跳转个界面,这个界面上我也没完全空着,加了个注销

2、系统实机演示

实机演示视频https://live.csdn.net/v/269198?spm=1001.2014.3001.5501

3、系统分析与设计

(1)主要软件与工具

工具:HUAWEI MATEBOOK D14(Windows 10)

软件:IntelliJ IDEA 2022.3,MySQL 8.0.28,Adobe Photoshop 2021,Microsoft Edge

(2)系统分析

登录注册系统需要具有的基本功能包括登录和注册两个部分。其中:

  1. 显性需求:提供注册信息写入服务,提供注册信息格式错误排查服务,提供登录检查服务;
  2. 隐性需求:注册部分应当考虑到用户对于自己设置的密码是否存在无意的输入错误(需求:需要二次确认密码);登录部分应到考虑到用户是否会忘记密码(需求:需要提供多种登录验证方式);
  3. 除此之外,还有一些便于后续开发而提供的需求,包括保存session以便向其他网页传递用户基本信息。

(3)系统规划

系统主要包括:数据库(MySQL)、后端诸项(Servlet,Util等)、前端诸项(JSP,CSS,JS)。

a. 数据库

需要在MySQL中新建用于存储用户信息(包含用户邮箱和密码字段)的数据库(database test)及其数据表(table user)。为了保障其他数据库的安全性,因此新建访问该数据库的用户("java"@"%")并赋以相应权限(all on test.*)。

b. 前端

需要设计三个界面,即:登录注册界面(index.jsp)、忘记密码登录界面(forgetPassword .jsp)、主界面(mainPage.jsp),及其附带的.js和.css文件。其中:

  1. 登录注册界面需要提供注册和常规账号密码登录两个子系统,并使用滑块进行子系统的切换。其中登录部分包含登录按钮、用于输入登录信息的两个输入框、用于切换到忘记密码登录界面的链接;注册部分则包含注册按钮,用于注册的三个输入框;除此之外还包括用于切换模式的两个按钮。
  2. 主界面为验证登录成功的跳转界面,本身无特殊价值和功能,仅加入了注销账户(即删除账户)的按钮,一键注销账户并同时跳转回登录注册界面。
  3. 忘记密码登录界面需要提供忘记密码登录服务,包含获取验证码的动态按钮、验证登录的按钮以及用于输入信息的两个输入框。

c. 后端

  1. DAO
  2. Util
    1. MailUtil.java:提供邮件发送的相关配置和邮件内容的拟写。
    2. JDBCUtil.java:提供数据库连接的相关配置。
    3. VCodeUtil.java:随机生成若干位包含大小写字母/数字验证码。
    4. User.java:提供存储临时用户、写入信息的方法从而便于传递参数。
  3. Servlet
    1. SignServlet.java:对应index.jsp,负责获取前端输入值并按照输入的信息判断启动相应的验证过程完成登录验证或注册。
    2. EmailServlet.java:对应forgetPassword.jsp,负责接收前端输入值并按照按键调用相应的方法(邮箱验证与验证码生成、发送,或核验验证码)。
    3. LogoutServlet.java:对应mainPage.jsp,主要目的是按照按键读取存储登录账户邮箱的session并注销该账户。

d. DAO.java:提供对数据库中的数据进行增删改查的方法。

e. 配置文件

web.xml:提供Servlet配置,并设置初始界面为index.jsp(登录注册界面)(注:这个东西极其重要,一开始的时候Servlet忘了在这里配置,结果前后端连不上,浪费了四五个小时。如何配置可以参考我后面的代码,也可以去其他博主那里查,但是务必要做好,做不好有的是哭的时候)。

4、系统设计与构建

(1)JavaWeb创建

关于JavaWeb创建的问题,由于我是基于IDEA做的,因此我就只给出IDEA创建JavaWeb项目的方法,链接如下:

IDEA社区版创建JavaWeb项目

IDEA专业版创建JavaWeb项目

一般来讲用IDEA专业版更保险,更舒适,更便捷,但是要花钱。不花钱的办法也有三个,其一是申请JetBrains的免费教育许可证(需要学生或教师身份),其二是破解(方法自己查),其三是利用一个月的试用期完成代码(你只有一个月)。

(2)JavaWeb运行

JavaWeb运行可以参见之前创建JavaWeb项目中给出的流程,由于我本人对于IDEA没有很熟悉,因此不过多评述,一切参照其他操作。

(3)先期依赖准备:

  • 依赖包下载方式:

    • 点开本人的主页,点击“查看详细资料”,添加好友获取依赖包(如果有问题同样可以通过这里问),本人承诺无特殊情况,三小时内将无条件提供依赖包(所谓特殊情况仅指时间上的,毕竟挂上去的是我的副号,获取信息可能不及时,见谅)。
    • 源码里面包含所需的包,理论上无需单独下载。
    • 通过本人CSDN资源免积分下载:

Activation-1.1.jar

javax.mail-1.6.2.jar

mysql-connector-j-8.0.31.jar

fastjson-2.0.21.jar

(那个fastJSON的本项目不需要)

  • 依赖包添加:

    • 第一步,按照之前给出的项目文件架构,在根目录下新建lib文件夹
    • 把下载好的依赖包(.jar文件)扔进去
    • 在IDEA里左侧的文件结构栏,右键.jar文件,点击“add as library”即可

5、代码与关键注释、文件简析

(注:注释是英文的,问就是写程序一直来回切换中英文实在过于麻烦,不想看英文的参见此处,包你满意)

(1)数据库

  • 新建数据库test:
create database test;
  • 新建用户java,密码为java,设置允许任何主机访问:
create user "java"@"%" identified by "java";
  • 授予用户java对test数据库的所有数据表的全部权限:
grant all on test.* to "java"@"%";
  • 在test库中新建数据表user:
create table user(
user_email char(100) primary key,
yser_password char(50)
);

(2)前端

  • index.jsp和styleIndex.css

JSP文件将登录和注册分置于两个表单,分别设置提交按钮进行表单的提交,从而保障一个servlet可以对应两个功能而不产生数据输入的冲突。利用嵌入的JS进行表单提交的中继。

添加用于切换登录/注册的按钮,切换动作通过更换各层的z-index和使用上层overlay进行不需要的模块的遮盖和切换滑块的移动。

使用轮播图进行背景的更换和展示,具体内容参考自他人代码。

index.jsp

<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>SIGN UP & SIGN IN</title><link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/8.0.1/normalize.min.css"><link rel="stylesheet" href="styleIndex.css"><script type="text/javascript">window.onload = function () {const signInBtn = document.getElementById("SignIn");const signUpBtn = document.getElementById("SignUp");const container = document.querySelector(".container");// Submit information formdocument.getElementById("form1");document.getElementById("form2");// Listen for switching action events and start related operationssignInBtn.addEventListener("click", () => {container.classList.remove("right-panel-active");});signUpBtn.addEventListener("click", () => {container.classList.add("right-panel-active");});}</script>
</head>
<body>
<div class="container right-panel-active"><%--Sign in--%><div class="container_form container--signin"><form action="SignServlet" method="post" class="form" id="form1"><h2 class="form_title">Sign In</h2><label for="user_email_1"></label><input type="email" id="user_email_1" name="user_email_1" required="required" placeholder="Email" class="input" /><label for="user_password_1"></label><input type="password" id="user_password_1" name="user_password_1" required="required" placeholder="Password" class="input" /><a href="forgetPassword.jsp" class="link">Forgot password?</a><button type="submit" class="btn" id="login">Sign In</button></form></div><%--Sign up--%><div class="container_form container--signup"><form action="SignServlet" method="post" class="form" id="form2"><h2 class="form_title">Sign Up</h2><label for="user_email_2"></label><input type="email" id="user_email_2" name="user_email_2" required="required" placeholder="Email" class="input" /><label for="user_password_2"></label><input type="password" id="user_password_2" name="user_password_2" required="required" placeholder="Password" class="input" /><label for="user_password_confirm"></label><input type="password" id="user_password_confirm" name="user_password_confirm" required="required" placeholder="Confirm Password" class="input" /><button type="submit" class="btn" id="register">Sign Up</button></form></div><%--Layer button--%><div class="container_overlay"><div class="overlay"><div class="overlay_panel overlay--left"><button class="btn" id="SignIn">Sign In</button></div><div class="overlay_panel overlay--right"><button class="btn" id="SignUp">Sign Up</button></div></div></div>
</div><%--Background carousel chart--%>
<div class="slidershow"><div class="slidershow--image" style="background-image: url('https://images.unsplash.com/photo-1575138312433-d42e9f176f6b?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=MXwxfDB8MXxhbGx8fHx8fHx8fA&ixlib=rb-1.2.1&q=80&w=1080&utm_source=unsplash_source&utm_medium=referral&utm_campaign=api-credit');"></div><div class="slidershow--image" style="background-image: url('https://images.unsplash.com/photo-1668952410266-e86775275752?crop=entropy&cs=tinysrgb&fit=crop&fm=jpg&h=720&ixid=MnwxfDB8MXxyYW5kb218MHx8fHx8fHx8MTY3MDMxMjQ0MQ&ixlib=rb-4.0.3&q=80&w=1080');"></div><div class="slidershow--image" style="background-image: url('https://images.unsplash.com/photo-1668016910564-3314f9fbd0bb?crop=entropy&cs=tinysrgb&fit=crop&fm=jpg&h=720&ixid=MnwxfDB8MXxyYW5kb218MHx8fHx8fHx8MTY3MDMxMjgxMA&ixlib=rb-4.0.3&q=80&w=1080');"></div><div class="slidershow--image" style="background-image: url('https://images.unsplash.com/photo-1669833526714-0bfa8a3b5cae?crop=entropy&cs=tinysrgb&fit=crop&fm=jpg&h=720&ixid=MnwxfDB8MXxyYW5kb218MHx8fHx8fHx8MTY3MDMxMzM5OA&ixlib=rb-4.0.3&q=80&w=1080')"></div>
</div>
</body>
</html>

styleIndex.css

/*Declaration: As for this code mainly refers to the achievements of others, some comments may have errors. Sorry about this.*/
:root {--white: #e9e9e9;--gray: #333;--blue: #095c91;--blue-r: #315a7491;--lightblue: #0393a3;--button-radius: 0.7rem;--max-width: 758px;--max-height: 420px;font-size: 16px;font-family: "Microsoft YaHei", tahoma, arial, sans-serif, "Hiragino Sans GB";}body {align-items: center;background-color: var(--white);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 0 1.25rem;
}
/*the link jumping to the forgetPassword page*/
.link {color: var(--gray);font-size: 0.9rem;margin: 1.5rem 0;text-decoration: none;text-align: justify;
}.container {background-color: rgba(255, 255, 255, 0.1);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%;z-index: 5;
}
/*Set moving elements*/
.container_form {height: 100%;position: absolute;top: 0;transition: transform 0.6s ease-in-out;
}
/*signin part*/
.container--signin {left: 0;width: 50%;z-index: 10;
}
/*signin part's moving settings*/
.container.right-panel-active .container--signin {transform: translateX(100%);
}
/*the same principal as above*/
.container--signup {left: 0;opacity: 0;width: 50%;z-index: 9;
}.container.right-panel-active .container--signup {-webkit-animation: show 0.6s;animation: show 0.6s;opacity: 1;transform: translateX(100%);z-index: 11;
}
/*Child body of "body". Set its style and move method*/
.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%);
}
/*Child container of "container". Set its style and move method*/
.overlay {background-color: rgba(255, 255, 255, 0.1);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%);
}/*Set move method of every single module for the button*/
.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-r);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: 1px solid transparent;padding: 0.9rem 0.9rem;margin:0.5rem 0;width: 100%;
}@-webkit-keyframes show {0%,49.99% {opacity: 0;z-index: 5;}50%,100% {opacity: 1;z-index: 6;}
}@keyframes show {0%,49.99% {opacity: 0;z-index: 5;}50%,100% {opacity: 1;z-index: 6;}
}.slidershow {position: absolute;width: 100vw;height: 100vh;overflow: hidden;
}.slidershow--image {position: absolute;width: 100%;height: 100%;background: no-repeat 50% 50%;background-size: cover;-webkit-animation-name: kenburns;animation-name: kenburns;-webkit-animation-timing-function: linear;animation-timing-function: linear;-webkit-animation-iteration-count: infinite;animation-iteration-count: infinite;-webkit-animation-duration: 16s;animation-duration: 16s;opacity: 1;-webkit-transform: scale(1.2);transform: scale(1.2);
}.slidershow--image:nth-child(1) {-webkit-animation-name: kenburns-1;animation-name: kenburns-1;z-index: 3;
}.slidershow--image:nth-child(2) {-webkit-animation-name: kenburns-2;animation-name: kenburns-2;z-index: 2;
}.slidershow--image:nth-child(3) {-webkit-animation-name: kenburns-3;animation-name: kenburns-3;z-index: 1;
}.slidershow--image:nth-child(4) {-webkit-animation-name: kenburns-4;animation-name: kenburns-4;z-index: 0;
}@-webkit-keyframes keyburns-1 {0% {opacity: 1;-webkit-transform: scale(1.2);transform: scale(1.2);}1.5625% {opacity: 1;}23.4375% {opacity: 1;}26.5625% {opacity: 0;-webkit-transform: scale(1);transform:scale(1);}100% {opacity: 0;-webkit-transform: scale(1.2);transform: scale(1.2);}98.4375% {opacity: 0;-webkit-transform: scale(1.21176);transform: scale(1.21176);}100% {opacity: 1;}
}@keyframes kenburns-1 {0% {opacity: 1;-webkit-transform: scale(1.2);transform: scale(1.2);}1.5625% {opacity: 1;}23.4375% {opacity: 1;}26.5625% {opacity: 0;-webkit-transform: scale(1);transform:scale(1);}100% {opacity: 0;-webkit-transform: scale(1.2);transform: scale(1.2);}98.4375% {opacity: 0;-webkit-transform: scale(1.21176);transform: scale(1.21176);}100% {opacity: 1;}
}@-webkit-keyframes kenburns-2 {23.4375% {opacity: 1;-webkit-transform: scale(1.2);transform: scale(1.2);}26.5625% {opacity: 1;}48.4375% {opacity: 1;}51.5625% {opacity: 0;-webkit-transform: scale(1);transform: scale(1);}100% {opacity: 0;-webkit-transform: scale(1.2);transform: scale(1.2);}
}@keyframes kenburns-2 {23.4375% {opacity: 1;-webkit-transform: scale(1.2);transform: scale(1.2);}26.5625% {opacity: 1;}48.4375% {opacity: 1;}51.5625% {opacity: 0;-webkit-transform: scale(1);transform: scale(1);}100% {opacity: 0;-webkit-transform: scale(1.2);transform: scale(1.2);}
}@-webkit-keyframes kenburns-3 {48.4375% {opacity: 1;-webkit-transform: scale(1.2);transform: scale(1.2);}51.5625% {opacity: 1;}73.4375% {opacity: 1;}76.5625% {opacity: 0;-webkit-transform: scale(1);transform: scale(1);}100% {opacity: 0;-webkit-transform: scale(1.2);transform: scale(1.2);}
}@keyframes kenburns-3 {48.4375% {opacity: 1;-webkit-transform: scale(1.2);transform: scale(1.2);}51.5625% {opacity: 1;}73.4375% {opacity: 1;}76.5625% {opacity: 0;-webkit-transform: scale(1);transform: scale(1);}100% {opacity: 0;-webkit-transform: scale(1.2);transform: scale(1.2);}
}@-webkit-keyframes kenburns-4 {73.4375% {opacity: 1;-webkit-transform: scale(1.2);transform: scale(1.2);}76.5625% {opacity: 1;}98.4375% {opacity: 1;}100% {opacity: 0;-webkit-transform: scale(1);transform: scale(1);}
}@keyframes kenburns-4 {73.4375% {opacity: 1;-webkit-transform: scale(1.2);transform: scale(1.2);}76.5625% {opacity: 1;}98.4375% {opacity: 1;}100% {opacity: 0;-webkit-transform: scale(1);transform: scale(1);}
}
  • forgetPassword.jsp和styleForgetPassword.css、sendMail.js

对表单排布进行限定,并利用margin属性和长度比例显示实现按键和输入框保持对其状态,此处考虑到表单分开提交无法满足验证表单需要两层数据的需求,因此将选择相应功能的逻辑交给了后端的EmailServlet。sendMail.js将后端传来的校验完成的信息进行响应,并提供更改获取验证码按钮上的倒计时的功能,控制按钮的启用和禁用。

(forgetPassword.jsp中包含的jquery-1.11.3.js文件需要另行下载,本人提供免积分下载的CSDN资源)

forgetPassword.jsp

<%@ page pageEncoding="UTF-8"%>
<%String path = request.getContextPath();String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%><!DOCTYPE HTML>
<html>
<head><base href="<%=basePath%>"><title>Sign In with Email</title><link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/8.0.1/normalize.min.css"><link rel="stylesheet" href="styleForgetPassword.css">
</head><body>
<form class="container" id="form" name="form" AUTOCOMPLETE="OFF"><form class="form"><h2 class="title">Sign In</h2><table><tr height="35px"><td><label for="user_email"></label><input type="text" name="user_email" id="user_email" placeholder="Email" class="input1" /></td><td><button id="btnGetVcode" class="btn1" style="cursor:pointer">Get Code</button></td></tr><tr height="35px"><td><label for="verification_code"></label><input type="text" name="verification_code" id="verification_code" placeholder="Verification Code" class="input2" /></td><td id="message"></td></tr></table><a target="_self"><button type="button" id="btnVerify" class="btn2" style="cursor:pointer">Sign In</button></a></form>
</form><div class="slidershow"><div class="slidershow--image" style="background-image: url('https://images.unsplash.com/photo-1575138312433-d42e9f176f6b?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=MXwxfDB8MXxhbGx8fHx8fHx8fA&ixlib=rb-1.2.1&q=80&w=1080&utm_source=unsplash_source&utm_medium=referral&utm_campaign=api-credit');"></div><div class="slidershow--image" style="background-image: url('https://images.unsplash.com/photo-1668952410266-e86775275752?crop=entropy&cs=tinysrgb&fit=crop&fm=jpg&h=720&ixid=MnwxfDB8MXxyYW5kb218MHx8fHx8fHx8MTY3MDMxMjQ0MQ&ixlib=rb-4.0.3&q=80&w=1080');"></div><div class="slidershow--image" style="background-image: url('https://images.unsplash.com/photo-1668016910564-3314f9fbd0bb?crop=entropy&cs=tinysrgb&fit=crop&fm=jpg&h=720&ixid=MnwxfDB8MXxyYW5kb218MHx8fHx8fHx8MTY3MDMxMjgxMA&ixlib=rb-4.0.3&q=80&w=1080');"></div><div class="slidershow--image" style="background-image: url('https://images.unsplash.com/photo-1669833526714-0bfa8a3b5cae?crop=entropy&cs=tinysrgb&fit=crop&fm=jpg&h=720&ixid=MnwxfDB8MXxyYW5kb218MHx8fHx8fHx8MTY3MDMxMzM5OA&ixlib=rb-4.0.3&q=80&w=1080')"></div>
</div>
<!-- 引入jQuery -->
<script type="text/javascript" src="jquery-1.11.3.js"></script>
<script type="text/javascript" src="sendEmail.js"></script>
</body>
</html>

styleForgetPassword.css

/*Basic settings of color and font set*/
:root {--white: #e9e9e9;--gray: #333;--blue: #095c91;--blue-r: #315a7491;--lightblue: #0393a3;--button-radius: 0.7rem;--max-width: 758px;--max-height: 420px;font-size: 16px;font-family: "Microsoft YaHei", tahoma, arial, sans-serif, "Hiragino Sans GB";}
/*Set body*/
body {align-items: center;background-color: var(--white);background-attachment: fixed;background-position: center;background-repeat: no-repeat;background-size: cover;display: grid;height: 100vh;place-items: center;
}
/*Set size and outer fill size*/
.title {font-weight: 300;margin: 0 0 1.25rem;
}
/*Set container*/
.container {background-color: rgba(255, 255, 255, 0.6);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);display: flex;flex-direction: column;height: var(--max-height);justify-content: center;max-width: 379px;overflow: hidden;padding: 0 3rem;position: relative;text-align: center;width: 100%;z-index: 5;
}.btn1 {background-color: var(--blue);background-image: linear-gradient(90deg, var(--blue) 0%, var(--lightblue) 74%);border: 0;color: var(--white);cursor: pointer;font-size: 0.8rem;font-weight: bold;letter-spacing: 0.1rem;padding: 1.2rem 1.7rem;
}.btn2 {background-color: var(--blue);background-image: linear-gradient(90deg, var(--blue) 0%, var(--lightblue) 74%);border-radius: 20px;border: 1px solid var(--blue-r);color: var(--white);cursor: pointer;font-size: 0.8rem;font-weight: bold;letter-spacing: 0.1rem;padding: 0.9rem 4rem;margin: 2rem 0 0 0;text-transform: uppercase;transition: transform 80ms ease-in;
}
/*Animation of click (transition)*/
.form > .btn2 {margin-top: 1.5rem;
}.btn2:active {transform: scale(0.95);
}.btn2:focus {outline: none;
}
/*Set input1, input2 to align the input box*/
.input1 {background-color: #fff;border: 1px solid transparent;padding: 0.9rem 0.9rem;margin: 0.5rem 0.6rem;width: 80%;
}.input2 {background-color: #fff;border: 1px solid transparent;padding: 0.9rem 0.9rem;margin: 0.5rem 0.6rem;width: 140%;
}
/*Picture carousel. Just to look good. I haven't got the specific principles. So here will no notes*/
@-webkit-keyframes show {0%,49.99% {opacity: 0;z-index: 5;}50%,100% {opacity: 1;z-index: 6;}
}@keyframes show {0%,49.99% {opacity: 0;z-index: 5;}50%,100% {opacity: 1;z-index: 6;}
}.slidershow {position: absolute;width: 100vw;height: 100vh;overflow: hidden;
}.slidershow--image {position: absolute;width: 100%;height: 100%;background: no-repeat 50% 50%;background-size: cover;-webkit-animation-name: kenburns;animation-name: kenburns;-webkit-animation-timing-function: linear;animation-timing-function: linear;-webkit-animation-iteration-count: infinite;animation-iteration-count: infinite;-webkit-animation-duration: 16s;animation-duration: 16s;opacity: 1;-webkit-transform: scale(1.2);transform: scale(1.2);
}.slidershow--image:nth-child(1) {-webkit-animation-name: kenburns-1;animation-name: kenburns-1;z-index: 3;
}.slidershow--image:nth-child(2) {-webkit-animation-name: kenburns-2;animation-name: kenburns-2;z-index: 2;
}.slidershow--image:nth-child(3) {-webkit-animation-name: kenburns-3;animation-name: kenburns-3;z-index: 1;
}.slidershow--image:nth-child(4) {-webkit-animation-name: kenburns-4;animation-name: kenburns-4;z-index: 0;
}@-webkit-keyframes keyburns-1 {0% {opacity: 1;-webkit-transform: scale(1.2);transform: scale(1.2);}1.5625% {opacity: 1;}23.4375% {opacity: 1;}26.5625% {opacity: 0;-webkit-transform: scale(1);transform:scale(1);}100% {opacity: 0;-webkit-transform: scale(1.2);transform: scale(1.2);}98.4375% {opacity: 0;-webkit-transform: scale(1.21176);transform: scale(1.21176);}100% {opacity: 1;}
}@keyframes kenburns-1 {0% {opacity: 1;-webkit-transform: scale(1.2);transform: scale(1.2);}1.5625% {opacity: 1;}23.4375% {opacity: 1;}26.5625% {opacity: 0;-webkit-transform: scale(1);transform:scale(1);}100% {opacity: 0;-webkit-transform: scale(1.2);transform: scale(1.2);}98.4375% {opacity: 0;-webkit-transform: scale(1.21176);transform: scale(1.21176);}100% {opacity: 1;}
}@-webkit-keyframes kenburns-2 {23.4375% {opacity: 1;-webkit-transform: scale(1.2);transform: scale(1.2);}26.5625% {opacity: 1;}48.4375% {opacity: 1;}51.5625% {opacity: 0;-webkit-transform: scale(1);transform: scale(1);}100% {opacity: 0;-webkit-transform: scale(1.2);transform: scale(1.2);}
}@keyframes kenburns-2 {23.4375% {opacity: 1;-webkit-transform: scale(1.2);transform: scale(1.2);}26.5625% {opacity: 1;}48.4375% {opacity: 1;}51.5625% {opacity: 0;-webkit-transform: scale(1);transform: scale(1);}100% {opacity: 0;-webkit-transform: scale(1.2);transform: scale(1.2);}
}@-webkit-keyframes kenburns-3 {48.4375% {opacity: 1;-webkit-transform: scale(1.2);transform: scale(1.2);}51.5625% {opacity: 1;}73.4375% {opacity: 1;}76.5625% {opacity: 0;-webkit-transform: scale(1);transform: scale(1);}100% {opacity: 0;-webkit-transform: scale(1.2);transform: scale(1.2);}
}@keyframes kenburns-3 {48.4375% {opacity: 1;-webkit-transform: scale(1.2);transform: scale(1.2);}51.5625% {opacity: 1;}73.4375% {opacity: 1;}76.5625% {opacity: 0;-webkit-transform: scale(1);transform: scale(1);}100% {opacity: 0;-webkit-transform: scale(1.2);transform: scale(1.2);}
}@-webkit-keyframes kenburns-4 {73.4375% {opacity: 1;-webkit-transform: scale(1.2);transform: scale(1.2);}76.5625% {opacity: 1;}98.4375% {opacity: 1;}100% {opacity: 0;-webkit-transform: scale(1);transform: scale(1);}
}@keyframes kenburns-4 {73.4375% {opacity: 1;-webkit-transform: scale(1.2);transform: scale(1.2);}76.5625% {opacity: 1;}98.4375% {opacity: 1;}100% {opacity: 0;-webkit-transform: scale(1);transform: scale(1);}
}

sendMail.js

const time0 = 60;  // Initial time
let time = time0;
let t;  // Timing$(document).ready(function() {// Getting verification code$("#btnGetVcode").click(function() {const btnGet = document.getElementById("btnGetVcode");btnGet.disabled = true;  // to avoid multiple clicks$.ajax({url: 'EmailServlet?method=getVCode',  // Choosing getCode methodtype: 'post',data: {user_email: $("input[name='user_email']").val()},dataType: 'text',success: function(msg) {if(msg === "-1"){window.alert("Incorrect Email.");btnGet.disabled = false;  // Disable button to avoid clicks before countdown being awakened}else if(msg === "0"){window.alert("No Such User. Please Sign In First.");btnGet.disabled = false;}else {useChangeBTN();  // If passing the verification, change the button and awake the countdown}},error:function(msg){}});});// 验证按钮$("#btnVerify").click(function() {document.getElementById("message");$.ajax({url: 'EmailServlet?method=verify',  // Choosing verify methodtype: 'post',data: {verification_code: $("input[name='verification_code']").val()},dataType: 'text',success: function(msg) {if(msg === "1"){window.alert("Welcome!")window.location.assign("mainPage.jsp");  // Jump to main page}else{window.alert("Wrong Verification Code!");}},error:function(msg){}});});
});// Function "changeBTN" is to start button display countdown and stop the disability of button when countdown ends
function changeBTN(){if(time > 0){$("#btnGetVcode").text("  "+time+" s  ");time = time - 1;}else{const btnGet = document.getElementById("btnGetVcode");btnGet.disabled = false;$("#btnGetVcode").text("Get Code");  // Show former wordsclearInterval(t);time = time0;  // Set back to the initial time}
}// Function "changeBTN" is to enable function "changeBTN"
function useChangeBTN(){$("#btnGetVcode").text("  "+time+" s  ");time = time - 1;t = setInterval("changeBTN()", 1000);  // refresh once time per second
}
  • mainPage.jsp和styleMainPage.css:

样使用submit类型的button进行表单的提交,但并不获取任何内容,只负责启动后端的LogoutServlet从而注销账户。

mainPage.jsp

<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>MAIN PAGE</title><link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/8.0.1/normalize.min.css"><link rel="stylesheet" href="styleMainPage.css"><script type="text/javascript">window.onload = function () {document.getElementById("form");}</script>
</head>
<body>
<div class="label"><form action="LogoutServlet" class="form"><h1 class="title">MAIN PAGE</h1><button type="submit" class="btnWF" id="write_off" name="write_off">Write Off</button></form>
</div>
<%--Background carousel chart--%>
<div class="slidershow"><div class="slidershow--image" style="background-image: url('https://images.unsplash.com/photo-1575138312433-d42e9f176f6b?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=MXwxfDB8MXxhbGx8fHx8fHx8fA&ixlib=rb-1.2.1&q=80&w=1080&utm_source=unsplash_source&utm_medium=referral&utm_campaign=api-credit');"></div><div class="slidershow--image" style="background-image: url('https://images.unsplash.com/photo-1668952410266-e86775275752?crop=entropy&cs=tinysrgb&fit=crop&fm=jpg&h=720&ixid=MnwxfDB8MXxyYW5kb218MHx8fHx8fHx8MTY3MDMxMjQ0MQ&ixlib=rb-4.0.3&q=80&w=1080');"></div><div class="slidershow--image" style="background-image: url('https://images.unsplash.com/photo-1668016910564-3314f9fbd0bb?crop=entropy&cs=tinysrgb&fit=crop&fm=jpg&h=720&ixid=MnwxfDB8MXxyYW5kb218MHx8fHx8fHx8MTY3MDMxMjgxMA&ixlib=rb-4.0.3&q=80&w=1080');"></div><div class="slidershow--image" style="background-image: url('https://images.unsplash.com/photo-1669833526714-0bfa8a3b5cae?crop=entropy&cs=tinysrgb&fit=crop&fm=jpg&h=720&ixid=MnwxfDB8MXxyYW5kb218MHx8fHx8fHx8MTY3MDMxMzM5OA&ixlib=rb-4.0.3&q=80&w=1080')"></div>
</div>
</body>
</html>

styleMainPage.css

:root {--white: #e9e9e9;--gray: #333;--blue: #095c91;--blue-r: #315a7491;--lightblue: #0393a3;--pink: #ff7f7f;--button-radius: 0.7rem;--max-width: 758px;--max-height: 420px;font-size: 16px;font-family: "Microsoft YaHei", tahoma, arial, sans-serif, "Hiragino Sans GB";}body {align-items: center;background-color: var(--white);background-attachment: fixed;background-position: center;background-repeat: no-repeat;background-size: cover;display: grid;height: 100vh;place-items: center;
}.label {background-color: rgba(255, 255, 255, 0);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);display: flex;flex-direction: column;height: var(--max-height);justify-content: center;max-width: 379px;overflow: hidden;padding: 0 3rem;position: relative;text-align: center;width: 100%;z-index: 5;
}.title {color: var(--white);font-size: 6rem;font-weight: 600;margin: 0 0 1.25rem;
}.btnWF {background-color: var(--blue);background-image: linear-gradient(90deg, var(--blue) 0%, var(--lightblue) 74%);border-radius: 20px;border: 1px solid var(--blue-r);color: var(--pink);cursor: pointer;font-size: 0.8rem;font-weight: bold;letter-spacing: 0.1rem;padding: 0.9rem 4rem;margin: 2rem 0 0 0;text-transform: uppercase;transition: transform 80ms ease-in;
}/*Animation of click (transition)*/
.form > .btnWF {margin-top: 1.5rem;
}.btnWF:active {transform: scale(0.95);
}.btnWF:focus {outline: none;
}@-webkit-keyframes show {0%,49.99% {opacity: 0;z-index: 5;}50%,100% {opacity: 1;z-index: 6;}
}@keyframes show {0%,49.99% {opacity: 0;z-index: 5;}50%,100% {opacity: 1;z-index: 6;}
}.slidershow {position: absolute;width: 100vw;height: 100vh;overflow: hidden;
}.slidershow--image {position: absolute;width: 100%;height: 100%;background: no-repeat 50% 50%;background-size: cover;-webkit-animation-name: kenburns;animation-name: kenburns;-webkit-animation-timing-function: linear;animation-timing-function: linear;-webkit-animation-iteration-count: infinite;animation-iteration-count: infinite;-webkit-animation-duration: 16s;animation-duration: 16s;opacity: 1;-webkit-transform: scale(1.2);transform: scale(1.2);
}.slidershow--image:nth-child(1) {-webkit-animation-name: kenburns-1;animation-name: kenburns-1;z-index: 3;
}.slidershow--image:nth-child(2) {-webkit-animation-name: kenburns-2;animation-name: kenburns-2;z-index: 2;
}.slidershow--image:nth-child(3) {-webkit-animation-name: kenburns-3;animation-name: kenburns-3;z-index: 1;
}.slidershow--image:nth-child(4) {-webkit-animation-name: kenburns-4;animation-name: kenburns-4;z-index: 0;
}@-webkit-keyframes keyburns-1 {0% {opacity: 1;-webkit-transform: scale(1.2);transform: scale(1.2);}1.5625% {opacity: 1;}23.4375% {opacity: 1;}26.5625% {opacity: 0;-webkit-transform: scale(1);transform:scale(1);}100% {opacity: 0;-webkit-transform: scale(1.2);transform: scale(1.2);}98.4375% {opacity: 0;-webkit-transform: scale(1.21176);transform: scale(1.21176);}100% {opacity: 1;}
}@keyframes kenburns-1 {0% {opacity: 1;-webkit-transform: scale(1.2);transform: scale(1.2);}1.5625% {opacity: 1;}23.4375% {opacity: 1;}26.5625% {opacity: 0;-webkit-transform: scale(1);transform:scale(1);}100% {opacity: 0;-webkit-transform: scale(1.2);transform: scale(1.2);}98.4375% {opacity: 0;-webkit-transform: scale(1.21176);transform: scale(1.21176);}100% {opacity: 1;}
}@-webkit-keyframes kenburns-2 {23.4375% {opacity: 1;-webkit-transform: scale(1.2);transform: scale(1.2);}26.5625% {opacity: 1;}48.4375% {opacity: 1;}51.5625% {opacity: 0;-webkit-transform: scale(1);transform: scale(1);}100% {opacity: 0;-webkit-transform: scale(1.2);transform: scale(1.2);}
}@keyframes kenburns-2 {23.4375% {opacity: 1;-webkit-transform: scale(1.2);transform: scale(1.2);}26.5625% {opacity: 1;}48.4375% {opacity: 1;}51.5625% {opacity: 0;-webkit-transform: scale(1);transform: scale(1);}100% {opacity: 0;-webkit-transform: scale(1.2);transform: scale(1.2);}
}@-webkit-keyframes kenburns-3 {48.4375% {opacity: 1;-webkit-transform: scale(1.2);transform: scale(1.2);}51.5625% {opacity: 1;}73.4375% {opacity: 1;}76.5625% {opacity: 0;-webkit-transform: scale(1);transform: scale(1);}100% {opacity: 0;-webkit-transform: scale(1.2);transform: scale(1.2);}
}@keyframes kenburns-3 {48.4375% {opacity: 1;-webkit-transform: scale(1.2);transform: scale(1.2);}51.5625% {opacity: 1;}73.4375% {opacity: 1;}76.5625% {opacity: 0;-webkit-transform: scale(1);transform: scale(1);}100% {opacity: 0;-webkit-transform: scale(1.2);transform: scale(1.2);}
}@-webkit-keyframes kenburns-4 {73.4375% {opacity: 1;-webkit-transform: scale(1.2);transform: scale(1.2);}76.5625% {opacity: 1;}98.4375% {opacity: 1;}100% {opacity: 0;-webkit-transform: scale(1);transform: scale(1);}
}@keyframes kenburns-4 {73.4375% {opacity: 1;-webkit-transform: scale(1.2);transform: scale(1.2);}76.5625% {opacity: 1;}98.4375% {opacity: 1;}100% {opacity: 0;-webkit-transform: scale(1);transform: scale(1);}
}

(3)后端(Servlet):

  • SignServlet.java

获取前端输入值后,根据user_password_confirm这一只存在于注册界面中的参数进行简单的功能判定,调用后端DAO中进行查询验证的Login方法或Register方法,进行登录或注册的验证与相关操作。在登陆验证过程中,如果通过验证,将跳转至主页面,同时新建session对象并获取session id,保存已登录的邮箱的信息。

package main.Servlet;import java.io.IOException;
import java.sql.Connection;import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;import main.DAO.DAO;
import main.Util.JDBCUtil;
import main.Util.User;// Servlet of Signing in and signing up
public class SignServlet extends HttpServlet {private static final long serialVersionUID = 1L;  // to ensure version compatibilityprotected void doPost(HttpServletRequest request, HttpServletResponse response)throws IOException {// Information entered by user when signing in: email, password.String user_email_1 = request.getParameter("user_email_1");String user_password_1 = request.getParameter("user_password_1");// Information entered by user when signing up: email, password and confirm password.String user_email_2 = request.getParameter("user_email_2");String user_password_2 = request.getParameter("user_password_2");String user_password_confirm = request.getParameter("user_password_confirm");response.setContentType("text/html;charset=utf8");JDBCUtil db = new JDBCUtil();DAO dao = new DAO();// The following statements are verifying input information and give related feedbacksif (user_password_confirm != null) {// Signing upString pattern = "^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)[0-9a-zA-Z]{8,12}$";boolean re = user_password_2.matches(pattern);User user = new User(user_email_2, user_password_2);try {Connection connection = db.GetConn();if (!user_password_2.equals(user_password_confirm)) {response.getWriter().println("<script>alert('Inconsistent passwords.')</script>");response.getWriter().println("<script>window.location.href='./index.jsp'</script>");} else if (!re) {response.getWriter().println("<script>alert('Passwords need more than eight digits including numbers and upper and lower case letters')</script>");response.getWriter().println("<script>window.location.href='./index.jsp'</script>");} else {dao.Register(connection, user);response.getWriter().println("<script>alert('Sign up successfully.')</script>");response.getWriter().println("<script>window.location.href='./index.jsp'</script>");}} catch (Exception e) {  // These statements can verify the existence of email address through integrity check service that mysql has providedresponse.getWriter().println("<script>alert('This user already exists.')</script>");response.getWriter().println("<script>window.location.href='./index.jsp'</script>");}} else {// Signing inUser user = new User(user_email_1, user_password_1);try {Connection connection = db.GetConn();if (dao.Login(connection, user) != null) {HttpSession session = request.getSession();  // Get sessionsession.setAttribute("email", user_email_1);  // Transferring information to sessionresponse.getWriter().println("<script>alert('Welcome!')</script>");response.getWriter().println("<script>window.location.href='./mainPage.jsp'</script>");} else {response.getWriter().println("<script>alert('Incorrect mailbox or password.')</script>");response.getWriter().println("<script>window.location.href='./index.jsp'</script>");}} catch (Exception e) {e.printStackTrace();}}}protected void doGet(HttpServletRequest request, HttpServletResponse response)throws IOException {this.doPost(request, response);}
}
  • EmailServlet.java

获取前端输入值,并提供由sendMail.js中给出的method参数进行方法的选择(在此处同样设置新建session并存储用户邮箱信息),然后根据不同选择调用不同的方法,其中利用正则表达式验证邮箱格式和利用DAO.java中的Exist方法验证邮箱是否是已注册邮箱,并将VCodeUtil.java生成并传到servlet的验证码和输入的验证码进行比对。两个验证的结果均添加相应标签传至前端JS文件以做出相应的响应。

package main.Servlet;import java.io.IOException;
import java.io.PrintWriter;
import java.sql.Connection;
import java.util.regex.Pattern;import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;import main.DAO.DAO;
import main.Util.EmailUtil;
import main.Util.JDBCUtil;
import main.Util.User;
// Servlet of forgetPassword page
// Class "EmailServlet" is to send verification code to user and to check the code
public class EmailServlet extends HttpServlet {private String user_email;private String vCode;  // Generated verification codeprivate String vCodeReceive;  // Entered verification codeprivate PrintWriter out;  // Output streamprivate final EmailUtil emailUtil = EmailUtil.instance;// Class "EmailServlet"'s construction methodpublic EmailServlet() {System.out.println("Monitoring point: Email Servlet");}protected void doGet(HttpServletRequest request, HttpServletResponse response)throws IOException {doPost(request, response);}protected void doPost(HttpServletRequest request, HttpServletResponse response)throws IOException {response.setContentType("text/html");request.setCharacterEncoding("utf-8");response.setCharacterEncoding("utf-8");out = response.getWriter();user_email = request.getParameter("user_email");  // Parameter "email" from fore-endvCodeReceive = request.getParameter("verification_code");  // Parameter "vcode" from fore-endString method = request.getParameter("method");  // Parameter "method" is to choose what method is neededswitch (method) {case "getVCode":  // when "Get Code button" is pressedtry {MGetVCode();} catch (Exception e) {throw new RuntimeException(e);}break;case "verify":  // when "Sign In button" is pressedHttpSession session = request.getSession();  // Get sessionsession.setAttribute("email", user_email);  // Transferring information to sessionMVerify();break;default:break;}out.flush();out.close();}// Method "MGetVCode" is to confirm email address and send verification codeprivate void MGetVCode() throws Exception {DAO dao = new DAO();User user = new User(user_email, null);JDBCUtil db = new JDBCUtil();Connection connection = db.GetConn();  // Configure connection and other thingsSystem.out.println("Monitoring point: Sending Verification Code");if(!IsEmail(user_email)) {  // Verify format of email addressout.print("-1");  // a label to make judgement of the condition of wrong formatreturn;  // Interrupt process} else {if (!dao.Exist(connection, user)) {  // Verify whether this email address is registeredout.print("0");  // a label to make judgement of the condition of nonexistent email addressreturn;}}try {emailUtil.SendEmail(user_email);  // Send verification code to target email address} catch (Exception e) {e.printStackTrace();}vCode = emailUtil.getVCode();  // Get and store the verification code sending just nowout.print("1");  // a label to make judgement of the condition}// Method "IsEmail" is to provide a method to confirm the format of email addressprivate boolean IsEmail(String email) {if(email.length() == 0) {return false;}Pattern pattern = Pattern.compile("^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\\.[a-zA-Z0-9_-]+)+$");  // Regular expressionreturn pattern.matcher(email).matches();}// Method "MVerify" is to verify whether the verification code is correctprivate void MVerify() {System.out.println("Monitoring point: Verify Verification Code");if(vCode.equals(vCodeReceive)) {out.print("1");  // a label to make judgement of the condition}else {out.print("-1");  // a label to make judgement of the condition}}public void destroy() {super.destroy();}@Overridepublic void init() throws ServletException {super.init();}
}
  • LogoutServlet.java

简单的调用session中存储的信息并调用DAO.java中提供的logout方法实现退出登录并注销账户。

package main.Servlet;import java.io.IOException;
import java.sql.Connection;import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;import main.DAO.DAO;
import main.Util.JDBCUtil;
import main.Util.User;// Servlet of writing off account
public class LogoutServlet extends HttpServlet {private static final long serialVersionUID = 1L;protected void doPost(HttpServletRequest request, HttpServletResponse response)throws IOException {String user_email_str;HttpSession session = request.getSession();Object user_email = session.getAttribute("email");  // Getting parameter from sessionuser_email_str = user_email.toString();JDBCUtil db = new JDBCUtil();DAO dao = new DAO();Connection connection = db.GetConn();User user = new User(user_email_str, null);if (dao.Logout(connection, user)) {response.getWriter().println("<script>alert('Can not write off.')</script>");response.getWriter().println("<script>window.location.href='./mainPage.jsp'</script>");} else {response.getWriter().println("<script>alert('Write off successfully.')</script>");response.getWriter().println("<script>window.location.href='./index.jsp'</script>");}}protected void doGet(HttpServletRequest request, HttpServletResponse response)throws IOException {this.doPost(request, response);}
}

(4)后端(Util)

  • MailUtil.java

注:此处涉及邮件SMTP协议的启动与关闭,可参照此文章(来自Wisdom0110):

使用JAVA实现邮件发送功能http://t.csdn.cn/ONKFk

package main.Util;import java.util.Date;
import java.util.Properties;import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;// Class "EmailUtil" is to configure the method sending email
public class EmailUtil {private static final String fromEmail = "2562521178@qq.com";  // Senderprivate static final String fromEmailPw = "################";  // Sender's passwordprivate static final String myEmailSMTPHost = "smtp.qq.com";  // Mail Serverprivate static Session session;  // Session objectprivate String vCode;  // Getting verification codepublic static EmailUtil instance = new EmailUtil();// Method "getVCode" is to get verification codepublic String getVCode() {return vCode;}// Method "EmailUtil" is to configure protocol, server, etcprivate EmailUtil() {Properties props = new Properties();props.setProperty("mail.transport.protocol", "smtp");  // SMTP protocolprops.setProperty("mail.smtp.host", myEmailSMTPHost);  // Recipient's email serverprops.setProperty("mail.smtp.auth", "true");  // Request authenticationsession = Session.getInstance(props);}// Method "CreateMailContent" is to edit messagepublic MimeMessage CreateMailContent(String toEmail) throws Exception {MimeMessage message = new MimeMessage(session);message.setFrom(new InternetAddress(fromEmail, "Verification Code Sending System", "UTF-8"));  // Sender's informationmessage.setRecipient(MimeMessage.RecipientType.TO, new InternetAddress(toEmail));  // Recipient's informationmessage.setSubject("Verification Code", "UTF-8");  // SubjectvCode = VCodeUtil.VerifyCode(6);  // Verification codemessage.setContent("Your verification code is " + vCode + ". Please do not show it to others. ", "text/html;charset=UTF-8");  // Main messagemessage.setSentDate(new Date());  // Datemessage.saveChanges();  // Save messagereturn message;  // Return Message}// Method "SendEmail" is to send message edited just nowpublic void SendEmail(String toEmail) throws Exception {Transport transport = session.getTransport();  // Create connectiontransport.connect(fromEmail, fromEmailPw);MimeMessage message = CreateMailContent(toEmail);transport.sendMessage(message, message.getAllRecipients());  // Sending emailtransport.close();  // Disconnection}
}
  • JDBCUtil.java

package main.Util;import java.sql.Connection;
import java.sql.DriverManager;// Class "EmailUtil" is to configure the connection to database
public class JDBCUtil {// Method "getConn" is to configure the connection to databasepublic Connection GetConn() {try {Class.forName("com.mysql.cj.jdbc.Driver");} catch (Exception e) {e.printStackTrace();}Connection conn = null;try {String dbUsername = "java";  // UsernameString dbPassword = "java";  // Password// Using 103.46.128.49:50691 to form remote connection in order to run this program on other connected deviceString dbUrl = "jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai";  // IP address, port, encoding, etc.conn = DriverManager.getConnection(dbUrl, dbUsername, dbPassword);  // Get connection} catch (Exception e) {e.printStackTrace();}return conn;}
}
  • VcodeUtil.java

package main.Util;import java.util.Random;// Class "VCodeUtil" is to generate verification code
public class VCodeUtil {public static String VerifyCode(int n) {StringBuilder strB = new StringBuilder();  // Character splicingRandom rand = new Random();for(int i = 0; i < n; i++) {int r1 = rand.nextInt(3);int r2 = 0;switch (r1) {  // Different type of characterscase 0:r2 = rand.nextInt(10) + 48;  // ASCII code value of numbersbreak;case 1:r2 = rand.nextInt(26) + 65;  // ASCII code value of uppercase lettersbreak;case 2:r2 = rand.nextInt(26) + 97;  // ASCII code value of lowercase lettersbreak;default:break;}strB.append((char)r2);  // Combine the letters into a six digit verification code}return strB.toString();}
}
  • User.java

package main.Util;// Class "User" is to access or modify data of user
public class User {private String user_email;private String user_password;public User() {}public User(String user_email, String user_password) {this.user_email = user_email;this.user_password = user_password;}public String getUser_email() {return user_email;}public String getUser_password() {return user_password;}public void setUser_email(String user_email) {this.user_email = user_email;}public void setUser_password(String user_password) {this.user_password = user_password;}
}

(5)后端(DAO)

  • DAO.java

向servlet提供了使用数据库信息的方法。其中写入了Login,Register,Exist,Logout四个方法,分别用于登录校验,注册写入,检查账户存在性,注销账户。

package main.DAO;import main.Util.User;import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Objects;// Class "DAO" is to configure the method operating database
public class DAO {// Method "login" is to provide data for login authenticationpublic User Login(Connection conn, User user)  throws Exception {User resultUser = null;  // Prepare result set "resultUser"String sql = "select * from user where user_email=? and user_password=?;";PreparedStatement pstatement = conn.prepareStatement(sql);  // Execute SQL statementpstatement.setString(1, user.getUser_email());pstatement.setString(2, user.getUser_password());  // Passing parameters to SQL statementResultSet rs = pstatement.executeQuery();  // Getting resultsif (rs.next()) {  // Traversing resultsresultUser = new User();  // Store results to result set prepared beforeresultUser.setUser_email(rs.getString("user_email"));resultUser.setUser_password(rs.getString("user_password"));}return resultUser;}// Method "register" is to store data of user while signing uppublic void Register(Connection conn, User user) throws Exception {String sql = "insert into user(user_email,user_password) values(?,?);";PreparedStatement pstatement = conn.prepareStatement(sql);pstatement.setString(1, user.getUser_email());pstatement.setString(2, user.getUser_password());pstatement.executeUpdate();}// Method "Exist" is to judge whether the entered email address exists while signing uppublic boolean Exist(Connection conn, User user) throws Exception {boolean flag = false;String sql = "select * from user;";Statement statement = conn.createStatement();ResultSet rs = statement.executeQuery(sql);String input_email = user.getUser_email();while (rs.next()) {  // Traversing results from database to see if entered email address has registeredString user_email = rs.getString("user_email");if (Objects.equals(user_email, input_email)) {flag = true;}}return flag;}// method "Logout" is to delete relevant user from databasepublic boolean Logout(Connection conn, User user) {boolean flag = false;try {String sql = "delete from user where user_email=?;";PreparedStatement pstatement = conn.prepareStatement(sql);pstatement.setString(1, user.getUser_email());pstatement.executeUpdate();} catch (Exception e) {flag = true;}return flag;}
}

(6)配置文件

  • web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"version="4.0"><display-name>WebProject</display-name><!--Setting home page--><welcome-file-list><welcome-file>index.jsp</welcome-file></welcome-file-list><!--Setting SignServlet--><servlet><servlet-name>SignServlet</servlet-name><servlet-class>main.Servlet.SignServlet</servlet-class></servlet><servlet-mapping><servlet-name>SignServlet</servlet-name><url-pattern>/SignServlet</url-pattern></servlet-mapping><!--Setting MailServlet--><servlet><servlet-name>EmailServlet</servlet-name><servlet-class>main.Servlet.EmailServlet</servlet-class></servlet><servlet-mapping><servlet-name>EmailServlet</servlet-name><url-pattern>/EmailServlet</url-pattern></servlet-mapping><servlet><servlet-name>LogoutServlet</servlet-name><servlet-class>main.Servlet.LogoutServlet</servlet-class></servlet><servlet-mapping><servlet-name>LogoutServlet</servlet-name><url-pattern>/LogoutServlet</url-pattern></servlet-mapping>
</web-app>

6、系统完成形式与参考代码

文件

完成形式

参考代码(或无参考)

index.jsp

改写

[1]

forgetPassword.jsp

改写

[2]

mainPage.jsp

自写

无参考

styleIndex.css

抄写(改正原代码错误)

[1]

styleForgetPassword.css

仿写、自写

[1]

styleMainPage.css

自写

[1]

sendEmail.js

改写

[2]

DAO.java

自写

[3]

EmailServlet.java

改写

[2]

SignServlet.java

自写

[3]

EmailUtil.java

改写

[2]

JDBCUtil.java

仿写

[3]

User.java

自写

无参考

VCodeUtil.java

抄写

[2]

[1]利用 css 和 Javascript 实现注册登录界面Ⅰ【每天一个不会秃头的前端案例】_哔哩哔哩_bilibili

[2]第二篇参考代码丢失(该部分代码主要是一个邮箱验证码登录的子系统)

[3]JavaWeb项目(登录注册页面)全过程详细总结

JavaWeb登录注册系统/界面(邮箱验证码,数据库连接,详细注释,可作结课作业,可用于学习,可接入其他主系统)相关推荐

  1. Python Socket联机自动匹配双人五子棋(含登录注册系统与界面,数据库连接,可作结课作业,可用于学习)

    1.前言 首先,关于源码的获取,本人提供了三种方式: 直接从文章里面Ctrl+C,Ctrl+V,然后按照我已给的文件结构搞一下即可: 通过积分下载上传到CSDN的资源: 点开本人的主页,点击" ...

  2. 【新手向】Python做一个简易登录注册GUI界面(无事件绑定)

    Python做一个简易登录注册GUI界面 一,效果展示 (1)运行结果: (2)点击登录: 注:只有用户名:123 密码123456 会提示登录成功. 登录成功示范: 登录失败示范: (3)点击注册 ...

  3. 青少年编程教育平台后台—登录注册(界面设计)

    青少年编程教育平台后台-登录注册(界面设计) 本界面使用HTML和CSS,未使用任何框架! 一.效果截图 二.HTML <!DOCTYPE html> <html><he ...

  4. 数据库结课作业——校园失物招领系统

    目录 杂七杂八 起因 项目环境 前端界面的选择 数据库理论阶段 数据库模型 代码实现 相关功能 UI设计 界面展示 项目总文件 项目代码(ui总文件在中) 杂七杂八 起因 因为数据库实验结课作业要结合 ...

  5. 项目的登录注册如何用邮箱发送验证码

    这里用QQ邮箱做样例 点击设置,点击账户,往下滑 把这里全都打开,然后一会下面代码中的授权码,就是这个页面中的生成授权码 using System; using System.Collections. ...

  6. Django练习——基于Mysql的登录注册功能界面(django模型、模板、表单简单应用)

    目录 1.创建 2.配置Mysql (1)连接数据库驱动 (2)创建表格 (3)创建迁移文件并同步到数据库 3.admin后台 (1)创建超级用户 (2)注册模型login_msg 4.路由与视图 4 ...

  7. 超详细编写登录注册页面(内含验证码登录)

    最近做项目,着实出师不利,刚登录就遇到bug,特在此记录一下,以此为鉴.首先,说明一下,这个登录页面内含验证码登录,当然也会有验证码验证,还有数据库没有设置加密,当然项目也没有强制要求,主要因为麻烦, ...

  8. WordPress登录注册评论滑动图片验证码插件腾讯云验证码(CAPTCHA)

    为了网站安全我们一般会在登录页.注册页.评论页添加验证码功能,传统的验证码都是输入字母数字或加减法等,现在比较流行图片滑动验证码.最为关键的是腾讯云提供有图形验证(图片滑动验证码)服务器(一年内提供几 ...

  9. java实现注册登录版五子棋对战平台(超详细注释,内含人机实现)

    目录 前言 项目介绍 功能演示 登录 注册 选择对手 落子提示 局时步时 查看战绩 落子五连 悔棋 聊天 新局 棋谱 保存棋谱 打开棋谱 其它功能 刷新 上下页 认输 退出 轮播图片 背景音乐 求助小 ...

最新文章

  1. 我是这样给阿里面试官吹 ConcurrentHashMap的
  2. OpenStack AMQP与kombu
  3. 数据中心运维管理社区祝大家新春快乐,虎年大吉!
  4. SAPMM模块配置目录
  5. SegNet 语义分割网络以及其变体 基于贝叶斯后验推断的 SegNet
  6. 1704班3组—高级软件测试作业—如何计算团队成员贡献分
  7. c 语言 单链表的操作 易考点
  8. 关于new handler与default、delete关键字
  9. oracle 查看监听命令_linux下使用Oracle常用命令
  10. C语言 数组排序 – 选择法排序 - C语言零基础入门教程
  11. installshield 脚本 在卸载过程执行_Linux下运行Jmeter脚本
  12. 在Macbook M1上安装Parallels Desktop 17虚拟机和Originlab 2021
  13. pdf转换成word后有文字叠加_word字体出现重叠 pdf转换成word
  14. mysql提权马免杀_webshell/牛逼免杀提权隐藏大马 (1).asp at master · tennc/webshell · GitHub...
  15. UA MATH524 复变函数4 复级数与复变函数的积分基础
  16. Java报表导出有哪些技术_报表工具能实现怎么的导出效果?
  17. 变形金刚之雷曼疯狂兔子:抽水马桶变身
  18. Alkyne-PEG-MAL 炔烃PEG马来酰亚胺
  19. 向量维数与向量空间维数的区别
  20. 02-nation.sql

热门文章

  1. 大于2T硬盘分区及格式化之Parted
  2. C/C++实现二叉树的遍历(深度优先,广度优先)
  3. 小程序中里的bindinput_微信小程序输入框input
  4. 微信小程序 输入框限制
  5. Maven--Maven常用插件及管理
  6. linux shell 函数库,bash shell 函数库
  7. 计算机视觉入门-梯度、算子、Canny边缘检测、非极大值抑制、双门限法
  8. 华为路由汇总(聚合)实验
  9. 将Linux中的AppImage变为桌面快捷方式
  10. python 文件后缀名 .py .pyc .pyw .pyo .pyd