基于Servlet、JSP的学生管理系统(附完整源码)

目录

前言

源码地址

界面截图

运行环境

主要功能

代码分析

首页数据统计

身份校验

其他



前言

2023/6/23 更新

这两年里,特别是每年期末的时候,有很多小伙伴咨询这个系统的问题。

大概总结了下,有几下几点:

1. 代码在哪儿?

放到了git上,代码地址:StudentManage: 基于Servlet、JSP、BootStrap的学生管理系统

2. 代码怎么运行?

有人反馈跑不起来,今天我特地试了下,只要严格按照我的另一篇教程来,肯定能跑起来的。何况这篇教程就是以这个小系统为例的,真跑不起来我也不会发出来。

idea如何运行Java Web项目(Servlet、JSP)_使用idea进行tomcat部署,访问webroot下的jsp页面_小楼夜听雨QAQ的博客-CSDN博客

3. 密码是多少?

默认密码如下,直接输入就行,不要想着改数据库密码,数据库里的密码是加密过的。

管理员账号:admin

管理员密码:123

学生账号:0000

学生密码:123

4. 数据库在哪配置?用什么版本?

数据库账号密码配置于:src目录下的druid.properties文件

数据库使用Mysql,编码格式utf8mb4,排序规则utf8mb4_general_ci,这是Mysql5.7和Mysql8都支持的,两个版本数据库都可以用。

如果登录不上去,看看控制台报错没。在密码确定正确的情况下,还有可能是数据库时区没有配置对,这个自己百度后改下就行。

5. 访问不了页面

只有可能是运行方式有问题,或者数据库没有配置正确,按照教程一步一步来即可。

————————————————————————————

2021/6/14更新

假期里我又重新完善了下代码,并把数据库改为了mysql5.7(当然,mysql8也兼容,但是需要自己换个jar包)。

有不少读者表示不会运行,或者运行起来报404。

一是因为数据库没有配置(找到druid.properties这个文件,改成自己的配置),二是因为上下文没有设置为StudentManage。

我写了一个比较详细点的教程:idea如何运行Java Web项目

关于版权问题就不要问我了,点赞 + 关注  =  代码拿过去随便用

下面是原文

——————————————————————————————————————————————————

最近重温servlet,想到了大学时期用同一个“学生管理系统”水了几门课的课程设计,不免感慨万千。

周末物料,简单的写了个界面,建了几张表,做了一个小系统。

写的比较简单,不过做个普通的课程设计应该够了,需要的自取。

源码地址

StudentManage: 基于Servlet、JSP、BootStrap的学生管理系统

界面截图

主界面

管理员界面

学生管理(管理员视角)

添加系统用户(管理员视角)

学生主页

学生个人信息

目录结构

运行环境

tomcat9

jdk1.8

mysql5.7

其他依赖jar包见WEB-INF下面的lib文件夹。

涉及技术:Servlet、JSP、BootStrap、Jquery(较少)

主要功能

系统有两个角色,管理员和学生。做的比较简单,没有建额外的角色表、权限表,仅仅用了一个字段区分。

管理员可以管理学生信息、教师信息、可以添加系统用户,录入成绩,具有增删改查的一切权限。

学生只能查看自己的分数,个人档案等。

代码分析

首页数据统计

系统运行时常、当前在线人数,这两个功能用到了servlet的组件,监听器。

通过继承ServletContextListener, HttpSessionListener, HttpSessionAttributeListener等接口,可以完成对servlet上下文、session的创建销毁等关键节点的监听。

在线人数,必然是登录成功的人数。

session是有人访问就会创建,所以我们不能根据session的创建和销毁来统计在线人数。

在登陆成功后,会在session里添加一个变量,我们可以监听这一行为。

当设置session变量的时候,在线人数+1

移除session变量的时候,在线人数-1。

当然这种做法还是有问题的,比如直接关闭浏览器,不点注销,数据统计就会失效,这里不做深入探究。

再来说说系统运行时长,我的思路是servlet上下文创建的时候,记录下那个时刻的时间戳。

后面用到的时候,直接用当前的时间戳减去保存的时间戳,就可以计算出相隔的毫秒数,也就可以得到天数。

@WebListener
public class CustomServerListener implements ServletContextListener, HttpSessionListener, HttpSessionAttributeListener {

	private volatile ServletContext application = null;
	//上下文初始化,记录当前时间的时间戳,初始化人数统计变量
	@Override
	public void contextInitialized(ServletContextEvent sce) {
		System.out.println("初始化开始---------");
		int onlineNum = 0;
		application = sce.getServletContext();
		application.setAttribute("onlineNum", onlineNum);
		application.setAttribute("startTime", new Date().getTime());
	}

	@Override
	public void contextDestroyed(ServletContextEvent sce) {
		ServletContextListener.super.contextDestroyed(sce);
	}

	//session创建的时候调用该方法。但是我们计算在线人数指的是登录成功的人
	@Override
	public void sessionCreated(HttpSessionEvent se) {
		
	}

	//连接断开
	@Override
	public void sessionDestroyed(HttpSessionEvent se) {
		
	}

	//
	@Override
	public void attributeAdded(HttpSessionBindingEvent se) {
		System.out.println("有人登录了---------");
		int onlineNum = (int) application.getAttribute("onlineNum");
		application.setAttribute("onlineNum", ++onlineNum);
	}
	
	

	@Override
	public void attributeRemoved(HttpSessionBindingEvent se) {
		System.out.println("有人退出了---------");
		int onlineNum = (int) application.getAttribute("onlineNum");
		application.setAttribute("onlineNum", --onlineNum);
	}

	@Override
	public void attributeReplaced(HttpSessionBindingEvent se) {
		
	}
}

计算统计数据的servlet

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		StudentService studentService = new StudentService();
		CourseService courseService = new CourseService();
		ScoreService scoreService = new ScoreService();
		int studentNum = studentService.count();
		int courseNum = courseService.count();
		int onlineNum = (int) request.getServletContext().getAttribute("onlineNum");
		long startTime = (long) request.getServletContext().getAttribute("startTime");
		List<ScoreDto> scoreList = scoreService.getTopScoreList(10);
		
		int days = (int)((new Date().getTime() - startTime) / (1000*3600*24)) + 1;
		request.setAttribute("studentNum", studentNum);
		request.setAttribute("courseNum", courseNum);
		request.setAttribute("onlineNums", onlineNum);
		request.setAttribute("days", days);
		request.setAttribute("scores", scoreList);
		
		
		
		
		request.getRequestDispatcher("/WEB-INF/pages/main.jsp").forward(request, response);
	}

身份校验

身份校验自然就用到了过滤器。

这边没有做复杂的角色权限校验,仅仅在用户表加上一个字段表示区分。

两个过滤器。

一个检查用户是否登录(有些页面需要登录,有些不需要的可以放行)

另一个检查权限够不够。

@WebFilter(value = "/*")
public class LoginFilter implements Filter {

	private static List<String> passUrlList = Arrays.asList("login.jsp", "css"
			, "js", "jpg", "loginUrl");

	/**
	 * Default constructor.
	 */
	public LoginFilter() {
		// TODO Auto-generated constructor stub
	}

	/**
	 * @see Filter#destroy()
	 */
	public void destroy() {
		// TODO Auto-generated method stub
	}

	/**
	 * @see Filter#doFilter(ServletRequest, ServletResponse, FilterChain)
	 */
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {
		HttpServletRequest req = (HttpServletRequest) request;
		HttpServletResponse resp = (HttpServletResponse) response;

		String uri = req.getRequestURI();
		// 登录页以及静态资源放行
		boolean needLogin = true;
		//页面名称
		String pageName = "";
		//后缀名
		String endName = "";
		if(uri.lastIndexOf("/") != -1 && uri.lastIndexOf("/") + 1 < uri.length()) {
			pageName = uri.substring(uri.lastIndexOf("/") + 1);
		}
		
		if(uri.lastIndexOf(".") != -1 && uri.lastIndexOf(".") + 1 < uri.length()) {
			endName = uri.substring(uri.lastIndexOf(".") + 1);
		}
		
		for (String passUrl : passUrlList) {
			if(passUrl.equals(pageName) || passUrl.equals(endName)) {
				//不需要登录
				needLogin = false;
			}
		}
		
		User user = (User) req.getSession().getAttribute("loginUser");
		
		if(needLogin && user == null) {
			//该资源需要登录,并且当前用户没有登录
			resp.sendRedirect("/StudentManage/login.jsp");
		}else {
			//不需要登录
			chain.doFilter(req, resp);
		}

		
	}

	/**
	 * @see Filter#init(FilterConfig)
	 */
	public void init(FilterConfig fConfig) throws ServletException {
		// TODO Auto-generated method stub
	}

}

权限校验过滤器

@WebFilter(value = "/admin/*", filterName = "B")
public class AuthenticationFilter implements Filter{

	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {
		// TODO Auto-generated method stub
		HttpServletRequest req = (HttpServletRequest) request;
		
		User user = (User) req.getSession().getAttribute("loginUser");
		Byte type = user.getUserType();
		if(type != 1) {
			//不是管理员,跳转到错误页面
			req.setAttribute("msg", "抱歉,您没有权限访问!");
			req.getRequestDispatcher("/WEB-INF/pages/error.jsp").forward(req, response);;
		}else {
			chain.doFilter(req, response);
		}
	}

}

其他

整体上写的随心所欲,不是很规范。

查找以及分页界面做了,后台没做。因为感觉没啥必要,原生的servlet知道基本原理和用法即可,写业务直接SpringBoot吧。

其他也没啥东西,不过路径跳转相关的,可以看下我的另一篇博客。

Servlet&JSP路径问题汇总

  • 124
    点赞
  • 509
    收藏
    觉得还不错? 一键收藏
  • 92
    评论
评论 92
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值