基于JSP的学生管理系统

                                -----------2019年6月1日更新-----------  

  

很感谢大家的阅读,不过在这里希望能够提几点学习前的问题。第一,其实我是不太建议各位去学习这一篇文章,毕竟这是我刚刚接触JavaWeb时写的项目,所以代码质量是不太好的,容易会出现Bug,再加上在JSP中写Java代码在开发中是不规范的,我是为了应付当时的作业才这样做。我更建议大家去看一下我另外一个项目:《基于Servlet的学生管理系统》,这里是基于这个项目,换一种技术进行重写的,里面有更多逻辑上的优化,排版也更舒服。如果希望进阶学习的话可以看下我的另外一篇文章:《【机房报修管理系统】1.简介篇 机房报修管理系统简介》,由于工作原因比较忙总是补不上前端篇的文章,可能在以后会填上这个坑的,在这里再次感谢各位读者的阅读,依然是那句话:“如果有疑问的地方,先百度,不行就写评论提问,最后没反应就发送邮件”。如果发送邮件三天内都没有回应,可能是我查阅邮件后忘了或者您的邮件被系统认为垃圾邮件导致我看不到,请重新发送或者写评论提示以下,一般写评论后我的邮箱是会收到邮件的。

                                -----------2019年5月6日更新-----------

时隔一年更新,发现有很多人在看本文章,也有不少人提出疑惑,由于我已经在上班,空闲时间不多,所以不能够及时给你们解答,在这里先说一声抱歉。其次有很多同学在部署后出现以下问题 ,出现原因已经写在评论中,请查看,也感谢这位热心的同学的解答。

一、摘要

 

        本系统前端是基于HTML+CSS+Bootstrap,后端基于纯JSP制作而成。由于是新手学习,当中的代码格式不够规范,还请各位多多包含。本项目已经在Github中开源,请各位大佬Star,Folk,Issue。

项目的总结构如图

 

数据库表:

所有表:

 

login表结构:

 

studentinfo表结构:

         

 

GitHub地址:我的GitHub

 

二、安装环境

 

  • 操作系统:MicroSoft Windows 10 1709
  • JAVA版本:1.8.0_172
  • 前端:HTML+CSS+JavaScript+BootStrap 4.0
  • 后端:Tomcat 8.5+JSP

三、实现功能和部分界面预览

 

  • 管理员登录系统
  • 学生资料的增加、修改、删除、查询
  • 管理员账号密码重置
  • 管理员退出系统
  • 登录界面
  • 主界面
  • 添加学生资料
  • 查询界面
  • 密码重置界面

四、安装方法

 

 

  1. 方法一:
  1. 访问我的GitHub:点击打开链接
  2. 下载我的项目(Down Zip)
  3. 解压后打开eclipse,File->Open Projects From File System,点击Directory选择刚刚解压出来的文件夹,点击finsh就行了。
  4. 使用Mysql命令执行我项目下MySQL文件夹里面的StudentManagementByWeb.sql脚本文件,还原数据库。
  5. 修改我项目下所有访问数据库的账号和密码的java语句,root改为自己的Mysql账户名,123456改为自己的Mysql相对应的密码。如这样的
  6. 看看项目环境是失效,如果失效通常项目都会有个红色小X的,只需要右键项目->Build Path->configure Build Path修复相对于失效的环境就行了。
  7. 运行TomCat,项目搭建完毕(账号和密码都是:admin)。
  8. 如果出现登录了正确的账号和密码后跳转的页面是空白,请按照第七点的第四小点进行操作。

方法二:

 

  1. 访问我的GitHub:我的GitHub
  2. 复制圈中的地址
  3. 打开Eclipse,File->Import,选择如图,然后按next
  4. 选择 clone URI,点击next
  5. 把复制的地址粘贴到URI栏,eclipse会自动补全下面的信息,然后不断点击next或Finsh直到项目导入。
  6. 执行方法一的步骤4~8
  7. 完成项目搭建。

 

 

 

五、关键代码段和思想

 

1.如何连接MySQL数据库?

如DAOCheckLogin.jsp中的部分代码

request.setCharacterEncoding("UTF-8");
	String user = request.getParameter("user");
	String password = request.getParameter("password");
	String sqlQuery = "SELECT * FROM stumanagementbyweb.login WHERE user='"+user+"'AND password='"+password+"'";
	try{
		Class.forName("com.mysql.cj.jdbc.Driver");
		Connection con = DriverManager.getConnection("jdbc:mysql://localhost:3306/stumanagementbyweb","root","123456");//创建一个Connection对象,DriverManager.getConnection("MySQL地址","MySQL账户名","MySQL密码");
		Statement sql = con.createStatement();//创建一个动作
		ResultSet rs = sql.executeQuery(sqlQuery);//把执行的结果放入到结果集中
		if(rs.next()){//遍历整个结果集,如果有下一行返回TRUE,没有则返回false
			session.setAttribute("user", user);
			session.setAttribute("id", rs.getString(1));
			response.sendRedirect("frame.jsp");
		}else{
			out.print("<script language='JavaScript'>alert('您的用户名或密码有误,请重新输入或者注册');window.location.href='Login.html'</script>");
		}
		con.close();
	}catch(SQLException e){
		e.printStackTrace();
	}

2.如何把数据库所有的数据显示在表格中?

    思想:先遍历学生信息数据表的每一行,然后使用JSP中的out.print()。

    做法:在Contain.jsp中有如下的代码段:

while(rs.next()){
			out.print("<tr>");
			out.print("<td>"+rs.getString(1)+"</td>");
			out.print("<td>"+rs.getString(2)+"</td>");
			out.print("<td>"+rs.getString(3)+"</td>");
			out.print("<td>"+rs.getString(4)+"</td>");
			out.print("<td>"+rs.getString(5)+"</td>");
			out.print("<td>"+rs.getString(6)+"</td>");
			out.print("<td>"+rs.getString(7)+"</td>");
			out.print("<td><a href='AlertStudent.jsp?id="+rs.getString(1)+"'><button class='btn btn-primary'>修改</button></a><a href='DaoDelete.jsp?id="+rs.getString(1)+"' onclick='javascript:return del();'><button class='btn btn-danger'>删除</button></a></td>");
			out.print("</tr>");
		}

当中的while(rs.next())就是遍历了学生信息表的每一行,所以利用rs.getString()来获取当前行的某一列,如第一列为rs.getString(1)如此类推。由于我在插入JSP代码是在HTML的表格<table></table>的范围中,所以能把所有信息以表格的形式列出来。

3.如何做到按一下修改按钮能够跳转到相应的页面并且显示修改的信息?

思想:在Contain.jsp中在遍历每一行数据时我都在超链接处留下一个相对应的id,让每一行的id通过URL进行传值,然后在DaoAlertStudent.jsp获取到相应的id,再进行数据库查询,从而得出当前行的信息。

做法:

out.print("<td><a href='AlertStudent.jsp?id="+rs.getString(1)+"'><button class='btn btn-primary'>修改</button></a><a href='DaoDelete.jsp?id="+rs.getString(1)+"' onclick='javascript:return del();'><button class='btn btn-danger'>删除</button></a></td>");

在此行代码中,我做了一个有超链接的按钮,超链接的地址指向AlertStudent.jsp,但是我在地址的后面还写了?id="+rs.getString(1),这样一来可以把当前行的id传给AlertStudent.jsp,只要在AlertStudent.jsp中写request.getParameter("id");就能够获得当前行的id。利用id进行数据库查询,得出当前行的信息,再把各个信息放在相对应的表单控件中就可以完成信息展示。

4.如何做到选择院部的时候专业的内容相对应会改变?

这种功能是通过JavaScript实现的,这样能减少访问数据库的次数。

这里要感谢以下文章地址的作者,我是仿照他的代码进行修改

点击打开链接

我仿照的代码,出自AddStudent.jsp

var librarians = ['机电工程学院', '电子信息学院', '工商管理学院', '财经管理学院', '汽车工程学院'];
		var choice = ['---请选择---'];
		var electromeChanical = ['数控技术', '模具设计与制造', '机械制造与自动化', '机电设备维修与管理', '工业机器人', '电气自动化', '机械设计与制造'];
		var electronicInformation = ['工业设计', '艺术设计', '光伏工程技术', '光伏发电技术与应用', '物联网应用技术', '计算机应用技术', '通讯技术', '电子信息工程技术'];
		var businessCircles = ['物流管理', '电子商务', '市场营销', '国际贸易实务', '工商企业管理', '商务管理'];
		var financialManagement = ['会计', '金融管理与实务', '财务管理', '酒店管理', '旅游管理'];
		var automobileEngineering = ['食品营养与检测', '汽车技术服务与营销', '汽车检测与维修技术'];

		var professional = new Array;
		professional[0] = choice;
		professional[1] = electromeChanical;
		professional[2] = financialManagement;
		professional[3] = businessCircles;
		professional[4] = electronicInformation;
		professional[5] = automobileEngineering;

		function add_option(select, option) {
			var target = document.getElementById(select);
			for(var i = option.length - 1; i >= 0; i--) {
				var add_option = document.createElement("option");
				add_option.text = option[i];
				target.add(add_option, null);
				target.lastChild.setAttribute("value", option[i]);
			}

		}
		add_option("college", librarians);

		document.getElementById("college").addEventListener("change", function() {

			var selevted_college = document.getElementById("college");
			var selected_major = document.getElementById("major");

			for(var i = selected_major.length - 1; i >= 0; i--) {
				selected_major.remove(i);
			}
			var selected = selevted_college.selectedIndex;
			if(selected == 0) {
				add_option("major", professional[0]);
			} else {
				add_option("major", professional[selected]);
			}
		})

 

5.如何防止访问者绕过登录界面访问其他页面?

思想:在一开始登录的时候检查用户是否正确,如果正确就建立一个session的会话,每个页面在进行操作之前都需要检查session会话是否为空,若为空则使用JavaScript提示需要登录并且强制跳转回登录界面。

做法:在DaoCheckLogin.jsp中检查输入的账号和密码是否正确,如果正确就执行一条语句session.setAttribute("user", user);,这条语句的意思是将user这个对象保存在session作用域中,而Session的生命周期是Session会话域,打开一个浏览器请求一个网站的页面后,Session开始,当Session超过时间限制后,Session注销而失效。

然后在每个页面的在执行JSP语句之前先检查user这个对象是否为空

 

if((String)session.getAttribute("user")==null){
			out.print("<script language='JavaScript'>alert('请先登录!');window.location.href='Login.html'</script>");
		}

如果user为空则输出一个JavaScript语句,弹出窗口说“请先登录!”并且强制跳转回登录页面。

附上DaoCheckLogin.jsp代码:

<%@page import="java.sql.SQLException"%>
<%@page import="java.sql.ResultSet"%>
<%@page import="java.sql.Statement"%>
<%@page import="java.sql.DriverManager"%>
<%@page import="java.sql.Connection"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<%

	request.setCharacterEncoding("UTF-8");
	String user = request.getParameter("user");
	String password = request.getParameter("password");
	String sqlQuery = "SELECT * FROM stumanagementbyweb.login WHERE user='"+user+"'AND password='"+password+"'";
	try{
		Class.forName("com.mysql.cj.jdbc.Driver");
		Connection con = DriverManager.getConnection("jdbc:mysql://localhost:3306/stumanagementbyweb","root","123456");
		Statement sql = con.createStatement();
		ResultSet rs = sql.executeQuery(sqlQuery);
		if(rs.next()){
			session.setAttribute("user", user);
			session.setAttribute("id", rs.getString(1));
			response.sendRedirect("frame.jsp");
		}else{
			out.print("<script language='JavaScript'>alert('您的用户名或密码有误,请重新输入或者注册');window.location.href='Login.html'</script>");
		}
		con.close();
	}catch(SQLException e){
		e.printStackTrace();
	}
%>
</body>
</html>

 

 

 

6.如何做到按左侧的侧边导航栏,网页能够在导航栏的右侧显示(如主界面)?

思想:这里涉及到了HTML的框架布局,可以点击此超链接查看相关内容   点击打开链接,设计好框架后把相应的网页放进框架中,导航栏那里的超链接的target属性记得是要填你想要显示框架的name属性的属性值。不然他会默认刷新超链接所在的当前框架。

做法:下面是我的frame.html代码(注意在框架页里面,框架不能在body元素中,必须要删除body元素,不然会不显示):

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<%
if((String)session.getAttribute("user")==null){
	out.print("<script language='JavaScript'>alert('请先登录!');window.location.href='Login.html'</script>");
}
%>
<frameset rows="10%,*" frameborder="0" framespacing="10">
		<frame src="Top.jsp" noresize="noresize" scrolling="yes" />
		<frameset cols="30%,*">
			<frame src="Left_nav.html" noresize="noresize" />
			<frame src="Contain.jsp" name="contain" />
		</frameset>
	</frameset>
</html>

大概的布局图就是这样:

我的Left_nav.html代码如下:

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title></title>
		<link rel="stylesheet" href="http://cdn.static.runoob.com/libs/bootstrap/3.3.7/css/bootstrap.min.css">
		<script src="http://cdn.static.runoob.com/libs/jquery/2.1.1/jquery.min.js"></script>
		<script src="http://cdn.static.runoob.com/libs/bootstrap/3.3.7/js/bootstrap.min.js"></script>
		<style type="text/css">
			ul{
				width: 200px;
				height: 200px;
				float: right;
				margin-top: 30px;
				
			}
		</style>
	</head>
	<body>
		<ul class="nav nav-pills nav-stacked">
			<li><a href="Contain.jsp" target="contain">学生管理</a></li>
			<li><a href="AdminPasswordReset.jsp" target="contain">账号密码重置</a></li>
			<li><a href="SystemExit.jsp" target="_parent">退出系统</a></li>
		</ul>

	</body>
</html>

我的超链接的target属性都是指向了contain,跳转的时候只有contain这个框架镜像刷新,这样就能做到问题的效果。

 

7.如果我的元素在框架中,但是我需要实现整个页面进行刷新或者跳转,我该怎样实现?

做法:一般来说,如果元素在框架中,如果不设置某些属性,当超链接跳转的时候只会在当前框架刷新,不会整个页面刷新,如果需要实现整个网页刷新,对应不同的情况有不同方法。

超链接:

<a href="SystemExit.jsp" target="_parent">退出系统</a>

target的属性值必须是“_parent”,属性解释请看下图或点击超链接        点击打开链接

 

JavaScript:

<script type='text/javascript'>window.parent.frames.location.href='Login.html';</script>

详细解释可以看这位作者的文章:点击打开链接

 

 

8.如何实现类似于百度分页的分页效果?

    思想:首先得要有两个概念,最大页和最小页,这个最小页(minPages)和最大页(maxPages)是用于接下来循环的边界(以下的什么当前页(pagesNo)-3,当前页(pagesNo)+3中的数字可以任意设置,看你分页需要有多长的需求,数字越大,分页显示的数字就越多)。最小页需要判断当浏览的当前页(pagesNo)-3页的时候是否小于0时,如果小于0便会越界,因为没有页数是负数的,所以需要检查当前页(pagesNo)-3页的时候如果小于0时,就需要把最小页变为1,如果不是小于0,则最小页为当前页-3页。最大页同理,如果当前页(pagesNo)+3页如果越过数据库所有数据所呈现的页数(pagesCount),则最大页只能是等于数据库所能所能提供的最大页数,否则最大页就是当前页+3。最后循环显示页数就能得到这样的效果。

    做法:

            代码出自Contain.jsp,可以对应上面的思想进行分析,下面有判断是否是当前页,如果是当前页则添加高亮css的class属性。

pagesCount = (lastRow % pageSize == 0) ? (lastRow / pageSize) : (lastRow / pageSize +1);
int minpages = (pagesNo - 3 >0) ? (pagesNo - 3) : 1;//使用了三目运算符
int maxpages = (pagesNo + 3 >= pagesCount) ? (pagesCount) : (pagesNo+3);
for(int i = minpages;i <=maxpages ;i++){
    if(i == pagesNo){//判断是否是当前页
        out.print("<li class='page-item active'>");
	out.print("<a class='page-link' href='Contain.jsp?pages="+i+"'>"+i+"</a>");
	out.print("</li>");
	}else{
	out.print("<li class='page-item'>");
	out.print("<a class='page-link' href='Contain.jsp?pages="+i+"'>"+i+"</a>");
	out.print("</li>");
	}
							
    }

 

9.如何实现分页当前页高亮效果?

    由于我是使用BootStrap,里面有一个class属性:.active,把这个属性放到相对应的class中就可以了,详情可以参考代码Contain.jsph和上面的第八点。也可以参考以下网址:点击打开链接

 

 

六、关于编程过程遇到的坑

1.明明html页面修改后提交到Tomcat,但是页面还是没有改变?

答:这是由于浏览器里面优先读取了缓存,即记录下你之前登录过这个系统的样式,浏览器这样做是为了能让网页访问速度更快,但是在这里却变成了绊脚石。解决方法有两个

    (1)设置HTML页面不缓存

            可以在HTML开头使用以下语句使HTML不缓存

<meta http-equiv="Expires" content="0">
<meta http-equiv="Pragma" content="no-cache">
<meta http-equiv="Cache-control" content="no-cache">
<meta http-equiv="Cache" content="no-cache">

    (2)每次进入更新HTML页面的时候使用CTRL+F5进行刷新,这样能不通过缓存进行刷新。

 

七、不足之处

    1.没有实现将所有查询到的数据分页显示,如果没有分页显示,现在数据库的数据量少还可以,但是一旦数据库有上千条数据,在显示的时候会导致一页往下拉全是数据,这样用户用起来体验就不好了。

<-------------------------------------------------2018年6月4日更新--------------------------------------------->

分页查询已经实现,请示通过数据库指定行数查询+id传值的方法就能够实现,详情看我GitHub源码的Contain.jsp。

改动后发现了新的Bug:

如果我的数据库有上千行语句,以每页显示10行来计算,需要100页,也就是100格,可是屏幕的空间根本不能够容下一行1000格的空间,所以分页元素极有可能会溢出。所以现在的解决思路是像百度那样分页,按下第10页,然后第10页移到中间,如此类推。

选中第10页前:

选中第10页后:

<-------------------------------------------------2018年6月7日更新--------------------------------------------->

修复了了上面分页的Bug,能够像百度的分页那样自动扩展页数并且增添了当前页高亮的效果。效果图如下:

第一页

第四页

第八页

    2.界面比较简单,毕竟理科生没有艺术细胞。在这里打个广告需要前端美工一名,没有工资

    3.开发过于随意,没有计划性。不管三七二十一先写了再说

    4.在登录界面第一次输入正确密码的时候,跳转时网页空白,控制台报错。

页面:

控制台:

         解决方法:我参考的方法:点击打开链接 这个是因为我选的JDBC版本太高(8.0),所以导致数据库的时区出错。解决方法可以在命令行登录了MySQL数据库,输入一下命令行:

set global time_zone='+8:00';

 

八、总结

        最近的JSP课程讲到了数据库的连接,然后我就试着用单纯的JSP来写这个学生资料管理系统,怎么说呢,我在以前有用过Java+Swing的形式做过一个学生管理系统的经验,项目地址:点击打开链接。所以这一次的项目我是按照上一次的经验做成的。虽然说代码量不大,估计前端+后端就700~800行,可是一个人兼顾前端和后端是真的累,以后要找个会前端的帮忙背锅(笑),花了大概3~4天的空闲时间,这次的开发也挺随性的,想到什么就写什么,完全没有开发流程的规范,在实现点击修改按钮就能修改当前行的功能时,还想了一早上都不知怎样实现,然后突然灵感一来,想到<form></form>能通过get方法让URL来传值,超链接也可以仿照get方法来传学号的值,再通过查询数据库就能获得当前的值了(其实直接把所有的内容通过传值获得,那就能减轻数据库的负担,这种方法更好,但是安全性不高),所以有时编程知识面和灵感也很重要。

        这一次的开发虽然是按照旧的经验做的,但是也学到很多东西,如BootStrap框架的使用,JavaScript的使用,等等。巩固了上课的内容,充实了自己,自己亲手把东西做出来后也是挺有成就感的,可能下次的作品还是学生管理系统,只是编程了使用各种框架,实现前端和后端分离的学生管理系统,还敬请期待。

 

 

相关推荐
©️2020 CSDN 皮肤主题: 技术黑板 设计师:CSDN官方博客 返回首页