提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
目录
一、项目演示和源码
1.1项目演示地址:会员管理系统
1.2源码地址:
二、设计目的
2.1项目背景
随着科学的飞速发展,Internet这个昔日只被少数科学家接触和使用的科研工具已经发展成了普通百姓都可触及的大众型媒体传输手段。随着用户的急剧增加,Internet的应用迅速进入到文化、产业、经济、政治、新闻、体育、娱乐、商业和服务业。各个行业都普及了Internet的应用,会员管理系统是Internet的一个重要应用领域,会员管理系统的开发,适合各大小商铺、理发店、娱乐场所的管理。
大量的大学理发店都没有自己的系统,会员的登记、理发预约、身份信息的更改等服务完全依靠管理人员操作,这样并不利于美发行业的发展和大大降低了工作人员的效率。因此,一个健全的管理系统是十分必要的,管理人员、会员、游客可以根据自己的权限,来自主完成的操作,提高工作效率。
本系统利用网络沟通、计算机信息存储管理,有着与传统的方式所无法替代的优点。比如计算检索速度特别快、可靠性特别高、存储容量特别大、保密性特别好、可保存时间特别长、开发成本低等。在工作效率上,能够得到极大地提高,延伸至服务水平也会有好的收获,有了网络,校园理发会员管理系统的各方面的管理更加科学和系统,更加规范和简便。
2.2项目目标
在学习的过程中,了解MVC的开发模式和开发环境,掌握前端、后端、数据库设计的知识,了解动态网页的开发过程,以及对书本上的知识加深印象,锻炼团队的合作与交流。完成项目的可行性分析、需求分析、框架设计、功能设计、界面设计等,再进行代码实现,完成项目实验的要求,最后,实验总结收获。
三、需求分析
随着科学的飞速发展,Internet这个昔日只被少数科学家接触和使用的科研工具已经发展成了普通百姓都可触及的大众型媒体传输手段。随着用户的急剧增加,Internet的应用迅速进入到文化、产业、经济、政治、新闻、体育、娱乐、商业和服务业。各个行业都普及了Internet的应用,会员管理系统是Internet的一个重要应用领域。通过Internet这一电子媒介,向人们展示了一种全新的、有别于传统的会员管理模式。会员管理系统的开发,适合各大小商铺、理发店、娱乐场所的管理。
3.1功能需求
(1)增添会员信息录入功能需求。可录入用户的基本信息以及店铺消费记录,包含用户姓名(可匿名),联系方式,年龄,住址,会员等级,会员卡号,账户积分,账务余额,账户状态。
(2)删除会员信息功能需求可对已录入用户的信息进行各种删除操作,包含单个信息的单独删除以及全部信息的删除。
(3)修改会员信息功能需求可对已录入用户的信息进行修改,除系统固定值外,其他数值均可进行修改。
(4)查询会员信息功能需求可对已录入用户的信息进行查询,查询方式为输入用户名,商家客户在完成注册登录后,可在网页中查看个人信息资料、包含会员信息。
3.2安全性需求
(1)用户名唯一,手机号码唯一,邮箱唯一
(2)用户名可用中文、大小写字母数组组成(3-16位)密码可有数字和字母组成(6-16位)
(3)不登陆无法查看个人信息,也无法查看会员信息
(4)代码数据、表单提交、url链接请求,AXAJ异步请求均采用POST请求方式
(5)本会员系统采用完备的密码管理系统,同时该系统的数据库管理系统实现了数据的保存和更新
3.3可靠性需求
(1)对已录入和修改的客户信息实现实时保存
(2)客户信息管理系统实时更新(在完成增添、删除、修改等功能后)
(3)本会员管理系统的目标系统功能基本齐全,能够完全满足校理发店的业务需求。理论上本系统能在大部分操作系统中正常运行,而各个模块接口能够保证完好。
四、概要设计
会员管理系统的用例图:
动态模型:
4.1登陆注册子系统
- 会员注册
- 会员登录
- 找回密码
- 查看基本信息
- 修改基本信息
- 退出系统
- 注销
登录注册子系统的用例图。
4.2会员信息管理子系统
会员信息:
- 搜索会员
- 查看会员列表
- 添加会员
- 查看会员信息
- 修改会员信息
- 删除会员
登录信息:
- 查看会员登录列表
- 查看会员登录信息
- 修改会员登录信息
会员信息管理子系统的用例图:
4.3详细的项目包图
五、开发环境
前端:html、css、javascript、jquery;
后端:Java、MySQL 8.0.31、JDK 1.8、Navicat 15
接口:JDBC
服务器:Tocmat 9.0
项目管理:Maven
开发工具:eslipse--EE
六、数据库设计
6.1数据库表的设计
max_user.db(管理员信息)
属性 | 名称 | 数据类型 | 约束条件 |
name | 用户名 | Varchar(20) | 主键、非空 |
password | 登入密码 | Varchar(20) | |
eamil | 邮箱 | Varchar(20) | |
phonenumber | 手机号码 | Varchar(11) |
users.db(用户信息)
属性 | 名称 | 数据类型 | 约束条件 |
id | 序号 | int | 主键、非空、自增 |
username | 用户名 | Varchar(20) | 非空 |
password | 登入密码 | Varchar(20) | |
age | 年龄 | Varchar(5) | |
sex | 性别 | Varchar(5) | |
phonenumber | 手机号码 | Varchar(20) | |
| 邮箱 | Varchar(20) | |
address | 地址 | Varchar(50) | |
creat_time | 创建时间 | Varchar(30) | |
id_number | 会员卡号 | Varchar(15) | |
member_class | 会员等级 | Varchar(10) | |
integral | 积分 | Int | |
balance | 余额 | Double(10,2) | |
status | 状态 | Varchar(10) | |
modif_time | 修改时间 | Datetime | |
login_time | 登入时间 | Varchar(30) |
6.2连接数据库
若采用三层架构的模式,JDBCUtil.java连接数据库,还需要建DAO.java,User.java,还有jsp,最后加一个servlet,再调用每一个类的方法。
JDBCUtil.java的代码:
public class JDBCUtil {
// 数据库的参数
private String dbUrl="jdbc:mysql://localhost:3306/my_login?useSSL=false";
private String dbUsername="root";
private String dbPassword="123456";
// 与数据库连接
public Connection getConn() {
try {
// 加载驱动
Class.forName("com.mysql.jdbc.Driver");
} catch (Exception e) {
e.printStackTrace();
}
Connection conn = null;
try {
// 获得连接,返回connection 对象
conn = DriverManager.getConnection(dbUrl, dbUsername, dbPassword);
} catch (Exception e) {
e.printStackTrace();
}
return conn;
}
}
七、效果展示 与部分核心代码
7.1普通用户部分
(1)登入界面
邮箱登录:(具体的操作在最后的特色功能中展示)
报错提示:
login.jsp(部分代码样式)
/*******************************************/
var user_template = `
<div class="account_input">
<div class="item">
<i class="user-icon"></i>
<input type="text" id="username" name="username" placeholder="请输入账号" autofocus="autofocus" required>
</div>
<div class="item">
<i class="pwd-icon"></i>
<input type="password" id="password" name="password" placeholder="请输入密码" required>
</div>
</div>
`
var phone_template = `
<div class="phone_input">
<div class="item_phone">
<i class="phone-icon"></i>
<input type="email" id="phone" name="email" placeholder="请输入邮箱" autofocus="autofocus" required>
</div>
<div class="item_check">
<input type="text" id="check" name="code" placeholder="请输入验证码" required>
<button class="getCode" type="button">获取验证码</button>
</div>
</div>
/*******************************************/
这里的获取验证码按钮需要用的AJAX请求。写在js/login.js中。
// 创建XMLHttpRequest
xhr.onreadystatechange = function () {
if (xhr.readyState == 4) {
// 请求已经完成,信息已经成功返回,开始处理信息
if ((xhr.status >= 200 && xhr.status < 300) || xhr.status == 304) {
// 将从服务器端返回是JSON格式数据转换成JavaScript对象
var res = xhr.responseText
var jsonObj = eval("("+res+")")
console.log("res:"+res)
if(jsonObj.type == 0) {
alert(jsonObj.error);
} else {
alert("邮箱发送成功,请查阅邮箱,尽快认证")
}
} else {
alert("邮箱发送失败")
}
}
}
xhr.open('POST','/T3/EmailServlet',true)
// 设置HTTP的输出内容类型为json格式数据:application/x-www-form-urlencoded
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded')
// 设置浏览器不使用缓存,服务器不从缓存中找,重新执行代码,而且服务器返回给浏览器的时候,告诉浏览器也不要保存缓存。
xhr.setRequestHeader('If-Modified-Since', '0')
// 发送请求
xhr.send("email="+email);
}/************************判断邮箱合法的else*/
/*******************************************/
LoginServlet.java(部分代码)
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 账号密码登录的方式
if(username != null && password != null) {/************如果这两个都为空,说明选择了邮箱登入********/
//解决中文字符乱码
byte[] bytes = username.getBytes("ISO-8859-1");
username = new String(bytes,"utf-8");
System.out.println(username);
JDBCUtil db = new JDBCUtil();
// 创建一个用户保存下将密码和用户名保存
User user = new User(username,password,email,login_time);
DAO dao = new DAO();
YanZheng yz=new YanZheng();
try {
//数据库连接
Connection conn = db.getConn();
if(dao.JudgeUser(conn, user)==false)//判断用户名是否存在
{
out.println("<h2>该用户不存在,请先去注册!<br>或者用户名错误,请重新输入!</h2>");
out.println("<h2>3秒以后返回登入界面页面</h2>");
response.setHeader("Refresh", "3;url=jsp/login.jsp");
}
else if(dao.login(conn, user) != null) {
request.getSession().setAttribute("member_user", user.getUsername());//用来查询信息,用户打印用户信息
dao.ModifLogin_time1(conn, user);//修改登入时间
response.sendRedirect("jsp/member_index.jsp");
} else {
out.println("<h1>用户名或者密码错误,验证失败</h1>");
out.println("<h2>3秒以后跳转回登录页面</h2>");
response.setHeader("Refresh", "3;url=jsp/login.jsp");
}
/********************邮箱登入验证********************/
else if(email != null && code != null) { //邮箱验证码方式*********少了验证QQ邮箱注册,否则没注册的也能登入*********
JDBCUtil db = new JDBCUtil();
User user = new User(username,password,email,login_time);
DAO dao = new DAO();
YanZheng yz=new YanZheng();
//数据库连接
try {
Connection conn = db.getConn();
// 判断emailCode是否正确
String s_emailCode = (String)request.getSession().getAttribute("emailCode");//调用存在服务器中的密码EmailServlet.java中
JsonResult jr = new JsonResult();
if(dao.JudgeEmail(conn, user)==false)
{
out.println("<h2>该邮箱不存在!或者输入的邮箱错误,请重新输入!</h2>");
out.println("<h2>3秒以后返回注册页面</h2>");
response.setHeader("Refresh", "3;url=jsp/login.jsp");
}
else if(!code.equalsIgnoreCase(s_emailCode)) {//接收表单的验证码和服务器上的验证码比对
out.println("<h1>邮件验证码错误,验证失败</h1>");
out.println("<h2>3秒以后跳转回登录页面</h2>");
response.setHeader("Refresh", "3;url=jsp/login.jsp");//AJAX跳转方式
} else { // 验证成功
request.getSession().setAttribute("member_user", user.getEmail());//用来查询信息,Member_index_ShowServlet.java用户打印用户信息
dao.ModifLogin_time2(conn, user);//修改登入时间
response.sendRedirect("jsp/member_index.jsp");}
/*********************************/
(2)用户注册界面
RegisterServlet.java(部分代码)
try {
//数据库连接
Connection conn = db.getConn();
if(yz.Username(username)==false)
{
out.println("<h2>输入的用户名不符合!</h2>");
out.println("<h2>3秒以后返回注册页面</h2>");
response.setHeader("Refresh", "3;url=jsp/register.jsp");
}
else {
if(dao.register(conn, user)==true) {//DAO.java中的函数,写入数据库
out.println("<h1>注册新用户成功</h1>");
out.println("<h2>3秒以后跳转回登入页面</h2>");
response.setHeader("Refresh", "3;url=jsp/login.jsp");
}
(3)用户找回密码
HandlepwdServlet.java(部分代码)
try {
//数据库连接
Connection conn = db.getConn();
// 数据库中没有该用户
if(dao.JudgeUser(conn, user)==false)//判断用户名是否存在
{
out.println("<h2>该用户不存在,请先去注册</h2>");
out.println("<h2>3秒以后返回修改密码页面</h2>");
response.setHeader("Refresh", "3;url=jsp/find_password.jsp");
}
/*************************************************/
else if(email != null && code != null) { //判断输入的验证码和生成的是否相同
// 判断emailCode是否正确
String s_emailCode = (String)request.getSession().getAttribute("emailCode");//调用存在服务器中的密码EmailServlet.java中
JsonResult jr = new JsonResult();
if(!code.equalsIgnoreCase(s_emailCode)) {//接收表单的验证码和服务器上的验证码比对
out.println("<h1>邮件验证码错误,验证失败</h1>");
out.println("<h2>3秒以后跳转回登录页面</h2>");
response.setHeader("Refresh", "3;url=jsp/find_password.jsp");//AJAX跳转方式
}
else {
if(dao.ModifPassword(conn, user)==true) {
out.println("<h1>修改密码成功</h1>");
out.println("<h2>3秒以后跳转回登录页面</h2>");
response.setHeader("Refresh", "3;url=jsp/login.jsp");
}
(4)用户注销
DeleteServlet.java(部分代码)
try {
//数据库连接
Connection conn = db.getConn();
if(yz.Username(username)==false)
{
out.println("<h2>输入的用户名不符合!</h2>");
out.println("<h2>3秒以后返回注册页面</h2>");
response.setHeader("Refresh", "3;url=jsp/register.jsp");
}
else {
if(dao.DeleteUser(conn, user)==true) {//DAO.java中的函数,写入数据库
out.println("<h1>注销用户成功</h1>");
out.println("<h2>3秒以后跳转回登入页面</h2>");
response.setHeader("Refresh", "3;url=jsp/login.jsp");
} else {//****************************后期需要改进,需要判断用户名是否存在;
out.println("<h1>密码错误,请重新输入!</h1>");
out.println("<h2>3秒以后跳转回注销页面</h2>");
response.setHeader("Refresh", "3;url=jsp/deleteuser.jsp");
}
}
(5)个人系统界面
7.2管理员部分
(1)登录界面
Max_login_Servlet.java(部分代码)
try {
//数据库连接
Connection conn = db.getConn();
if(dao.JudgeUser(conn, user)==false)//判断用户名是否存在
{
out.println("<h2>该用户不存在!<br>或者用户名错误,请重新输入!</h2>");
out.println("<h2>3秒以后返回登入界面页面</h2>");
response.setHeader("Refresh", "3;url=jsp/Max_Login.jsp");
}
else if(dao.login(conn, user) == null) {//判断用户名和密码是否对的上
out.println("<h1>用户名或者密码错误,验证失败</h1>");
out.println("<h2>3秒以后跳转回登录页面</h2>");
response.setHeader("Refresh", "3;url=jsp/Max_Login.jsp");
}
else {
//request.getSession().setAttribute("user", user);
request.getSession().setAttribute("max_user", user.getUsername());//用来管理员登入了,直接查看网页看不到,ShowServlet.java在打印
response.sendRedirect("jsp/index.jsp");
}
(2)找回密码界面
// 修改密码验证,并修改密码
public boolean ModifPassword(Connection conn,User user) throws Exception {
boolean flag = false;
// sql 查询语句
String sql="update Max_user set password=? where name=?";
// 获得执行sql语句的对象
PreparedStatement pstatement =conn.prepareStatement(sql);
pstatement.setString(1, user.getAgain_password());
pstatement.setString(2, user.getUsername());
// 执行sql语句获得结果集
int res = pstatement.executeUpdate();
if(res > 0) {
flag = true;//则修改密码成功
}
return flag;
}
(3)管理系统界面
ShowServlet.java(部分代码)
//数据库连接
Connection conn = db.getConn();
/*******************************************/
if(dao.JudgeUser(conn, user)==true)//判断管理员是否登入。
{
Statement stmt=conn.createStatement();
String sql="select*from users";
ResultSet rs=stmt.executeQuery(sql);
ArrayList<User> list=new ArrayList<User>();
while(rs.next())
{
User info=new User();
info.setId(rs.getString("id"));
info.setUsersname(rs.getString("username"));
。。。。。。
info.setLogin_time(rs.getString("login_time"));//登入时间
list.add(info);
}
HttpSession session = request.getSession();
session.setAttribute("list",list);
/*******************************************/
(4)添加用户
(5)修改某一个用户的信息
(6)删除用户
八、特殊功能
8.1图片验证码
Validate.jsp
<!DOCTYPE html>
<body>
<%
response.setContentType("image/jpeg;charsert=utf-8");//关键,防止图片变成乱码
response.setHeader("Cache-Control","no-cache");
//在内存中创建图像
int width=60,height=20;
BufferedImage image=new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
//获取笔画
Graphics g=image.getGraphics();
//设置背景
g.setColor(new Color(200,200,200));
g.fillRect(0, 0, width, height);
//随机产生的验证码(4位数)
Random rnd=new Random();
int randNum=rnd.nextInt(8999)+1000;
String randStr=String.valueOf(randNum);
//将验证码存入session
session.setAttribute("randStr",randStr);
//将验证码显示到图像中
g.setColor(Color.black);
g.setFont(new Font(" ",Font.PLAIN,20));
g.drawString(randStr, 10, 17);
//随机产生100个干扰点,是图像中的验证码不易被其他程序探测到
for(int i=0;i<100;i++)
{
int x=rnd.nextInt(width);
int y=rnd.nextInt(height);
g.drawOval(x, y, 1, 1);
}
//输出到图像页面
ImageIO.write(image,"JPEG",response.getOutputStream());
out.clear();
out=pageContext.pushBody();
%>
</body>
</html>
调用生成的验证码:
8.2QQ邮箱验证码
首先,打开QQ邮箱,点击设置,点击账户,找到下面的信息,将下面几个服务开启,即可使用QQ邮箱发送短信。
发送邮箱代码: MailUtil.java
public class MailUtil {
public void sendMail(String userEmail, String emailMsg) throws Exception {
// 1. 创建一封邮件,创建一个程序与邮件服务器会话对象session
Properties props = new Properties();
props.setProperty("mail.transport.protocol", "SMTP");
props.setProperty("mail.host", "smtp.qq.com"); //smtp.126.com为SMTP服务器地址,为指定这个服务器发送邮件
props.setProperty("mail.smtp.auth", "true"); // 指定验证为true
// 创建验证器
Authenticator auth = new Authenticator() {
public PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication("2728356829@qq.com", "ifmiphqeoegpdhdj"); //参数分别为:用户名和授权密码
}//发送方的信息(用来固定发送邮件的)
};
// 用于连接邮件服务器的参数配置(发送邮件时需要用到)
Session session= Session.getInstance(props,auth); // 根据参数配置,创建会话对象(为了发送邮件准备的)
// 2.创建邮件对象message,相当于邮件内容
Message message = new MimeMessage(session);
// From: 发件人
// 其中 InternetAddress 的三个参数分别为: 邮箱, 显示的昵称(只用于显示, 没有特别的要求), 昵称的字符集编码
// 真正要发送时, 邮箱必须是真实有效的邮箱。
message.setFrom(new InternetAddress("2728356829@qq.com","哈哈哈","UTF-8"));
// To: 收件人 设置收件人和发送方式
message.setRecipient(MimeMessage.RecipientType.TO, new InternetAddress(userEmail));
// Subject: 邮件主题
message.setSubject("邮箱验证");
// Content: 邮件正文(可以使用html标签)
message.setContent(emailMsg, "text/html;charset=UTF-8");
// 3. 创建 transport 用于将邮件发出
Transport.send(message);
}
}
EmailServlet.java中调用生成邮箱的方法,包括邮箱的内容、发送
发送成功后:
九、总结
在这次项目开发的过程中,大致认识到了整体的开发流程,也时逐渐明白了在开发过程中每一部分的重要性。比如在需求分析这一类最初的认识就是需要什么功能,到后来才明白需要完成很多文档工作和绘图,同时这篇分析对于整体项目的影响。在完成本次项目的开发后也认识到自己许多的不足,在往后定然会虚心学习,认真完成到手的每一项任务。