简介:这是一份面向Java初学者的课堂考勤管理系统完整源码,后端采用Spring+SpringMVC+Mybatis(SSM)组合,前端使用JSP与layui框架,并基于Maven构建,非常适合用于课程设计、毕业设计或SSM整合实战练习。系统内置辅导员、管理员、教师、学生四种角色,覆盖班级管理、学生管理、签到发布与记录、请假审批等典型业务场景,角色权限划分清晰,适合二次开发与学习。资源包共1802个文件,包含大量JSP页面、Java类、XML配置、JS/CSS静态资源、SQL脚本及JAR依赖,其中gif/png图片多用于界面展示或说明文档,整体目录结构完整,压缩包大小33.32MB,解压即可导入IDE运行。项目运行环境建议为JDK1.8、Tomcat7/8/9、MySql5.7,描述中也给出了IDEA/Eclipse等IDE的配置参考,便于快速搭建环境。已有767人学习下载,适合希望完整跑通SSM项目或在此基础上扩展签到、请假等功能的开发者。
1. 学生课堂考勤管理系统:这个 SSM 项目解决的是谁的痛点
纸质点名一节课要花三五分钟,代答到、事后补签更是防不住;请假条层层递送,辅导员和任课老师的信息永远对不上。这套基于 Java + SSM + JSP + layui + MySQL 的学生课堂考勤管理系统,把管理员、辅导员、教师、学生四种角色拉进同一条业务链,从排课、建班、录入学生,到发起签到、提交请假、审批统计,全部在线闭环。它的价值不在代码量,而在业务边界划分得清楚:管理端只做基础数据维护,教师端只管签到现场,学生端只做签到和请假,辅导员则卡在中间的审批节点上。适合正在做课程设计、毕业设计,或者刚学完 SSM 想找一个完整多角色项目的读者。下面按我从导入到跑通再到改业务的实际顺序,把这套代码拆开讲。
2. 四角色权限拆解:管理员、辅导员、教师、学生各管哪一段
2.1 管理员端:班级、教师、辅导员三张基础表的维护
管理员是这个系统里权限最高但操作最“无聊”的角色,没有花哨业务,只有基础数据维护。登录后能看到班级管理、辅导员管理、教师管理三个功能模块。这里的逻辑是:考勤系统要运转,首先得有稳定的组织架构——班级表决定了哪些学生属于同一个考勤单位,教师表决定了谁有权限发起签到,辅导员表决定了请假审批的归属人。
很多初次做 SSM 项目的人容易忽略一个细节:这三张表不是独立存在的,它们通过外键关联形成一棵数据树。班级表里通常会带一个辅导员字段或者关联字段,学生表里带班级字段,签到记录表里带学生和课程字段。理解了这个依赖顺序,你就能明白为什么登录后台第一件事是先把班级、教师、辅导员数据录进去,而不是急着去测签到功能。
实际操作中,管理员的页面大多是表格 CRUD:新增一条教师记录、把一个辅导员分配到某个班级、把一个班级改名或归档。代码层面就是标准的 ModelAndView 跳转加 MyBatis 的 insert/update/delete,没有复杂算法,但它是整个系统的地基。地基如果乱,后面所有角色的列表都会跟着错。
2.2 辅导员:学生档案与请假审批的双重身份
辅导员这个角色在系统里承担的是“审核人”和“数据维护人”的双重职责。功能清单里写的是:辅导员登录、学生管理、密码修改、请假审批、签到列表。拆开来看,学生管理对应的是所辖班级的学生档案维护,比如新生入学时批量录入、学生转专业时修改归属、毕业时标记离校。
请假审批是辅导员最核心的差异化功能。流程是:学生提交请假申请,辅导员看到申请后选择通过或驳回。这个状态流转看起来简单,但实际影响后续所有统计——如果审批状态没有及时更新,教师端看到的请假列表就会滞后,签到记录里也会出现“未请假但缺席”的误判。
我建议拿到代码后先翻一下数据库里请假表和签到表的关系字段。常见的坑是请假表只存了学生 ID 和状态,没有关联到具体的课程或节次,导致“上午请假下午到课”这种场景没法被精确处理。这套项目用的是简化模型,请假通常按天或按时间段记录,够用但边界要清楚。
2.3 教师端:签到管理与请假列表的现场控制
教师的操作集中在课堂现场:登录后发起签到、查看签到情况、处理请假相关的查看。签到管理是这里的重头戏,教师可以选择当前班级,发起一次签到,然后系统生成一个签到记录,学生端就能看到“开始签到”的入口。
从实现角度看,签到功能通常是 SignController 在驱动。一个典型的流程是:教师点击“发起签到”,前端 AJAX 请求后端创建一个签到记录,记录里包含课程 ID、班级 ID、发起时间;学生端页面轮询或者手动刷新,看到有进行中的签到就点击“签到”,系统写入一条签到记录并标记时间。
这里有一个值得注意的设计选择:签到按钮的开放窗口期。有的实现是教师发起后长期有效,有的实现是限时 30 秒或 1 分钟自动关闭。如果项目代码里没有限时逻辑,你可以在发起签到的接口里加一个过期时间字段,每次学生提交签到前校验当前时间是否在窗口内。这样既防止学生提前签,也防止课后补签。
2.4 学生端:开始签到、我的签到与请假申请
学生端的入口最频繁,功能最轻:登录后看到“开始签到”“我的签到”“请假管理”“修改密码”。开始签到是学生唯一被动的动作——教师发起后,学生点击按钮提交;我的签到是查询历史记录,看自己哪天缺勤、哪天迟到;请假管理则是提交申请和跟踪审批状态。
学生端的设计重点在“少让用户思考”:按钮要醒目、状态要即时反馈。如果用 layui 做前端,常见做法是页面加载时先查一次签到状态,如果当前有进行中的签到,就显示一个大的“点击签到”按钮;没有则显示“当前无签到任务”。这个状态查询的频率要控制好,每次进入页面查一次就够了,不要做轮询,否则并发一大数据库扛不住。
功能矩阵整理如下:
| 角色 | 核心菜单 | 关键操作 | 数据权限范围 |
|---|---|---|---|
| 管理员 | 班级、辅导员、教师 | 增删改查 | 全校基础数据 |
| 辅导员 | 学生、请假审批、签到列表 | 审核、维护 | 所辖班级 |
| 教师 | 签到管理、请假列表 | 发起签到、查看 | 授课班级 |
| 学生 | 开始签到、我的签到、请假管理 | 签到、提交请假 | 本人记录 |
3. SSM 环境与项目导入:从 JDK 1.8 到 Tomcat 的完整配置过程
3.1 运行环境选型:为什么是 JDK 1.8 + MySQL 5.7 + Tomcat 7-9
这套项目要求的运行环境是 JDK 1.8、MySQL 5.7、Tomcat 7.x/8.x/9.x 均可,Maven 项目。这个组合其实是非常成熟的“保守派”搭配——SSM 框架本身对 JDK 版本的依赖就偏向 1.8,因为 Spring 4.x 和 MyBatis 3.x 的很多特性就是在 JDK 8 上验证过的,切到高版本 JDK 反而可能出现代理相关的问题。
MySQL 5.7 也是同样的逻辑。5.7 对 SQL 语法的兼容性最好,项目里自带的初始化脚本基本是为 5.7 写的,放到 8.0 上面跑容易碰到时区、认证插件和驱动版本三个问题。如果你机器上已经装了 MySQL 8.0,建议先建一个 5.7 的容器或者换用 5.7 的免安装包,等跑通之后再去适配高版本。
Tomcat 的选择范围 7-9 覆盖了绝大多数课程设计和毕业设计的部署环境。注意一点:Tomcat 10 之后包名从 javax.servlet 换成了 jakarta.servlet,这套代码如果直接丢进 Tomcat 10 会报编译错误或者运行时 ClassNotFound,所以别贪新。
3.2 Maven 依赖与项目导入:IDEA 中的操作步骤
拿到项目后第一步不是急着点运行,而是先确认环境变量。依次执行下面三条命令:
java -version mvn -v mysql --versionjava -version 确认 JDK 版本是 1.8;mvn -v 确认 Maven 已安装并能在命令行调用;mysql --version 确认数据库版本。三条命令都有正常输出之后,再用 IDEA 打开项目根目录下的 pom.xml,IDEA 会识别为 Maven 项目并开始解析依赖。
mvn clean compile这条命令用于在命令行阶段提前暴露依赖缺失问题。如果提示某个包下载失败或者找不到符号,先检查本机 Maven 的 settings.xml 里是否配置了阿里云镜像,没有的话需要加上。等编译通过,再回到 IDEA 里配置 Tomcat:Run -> Edit Configurations -> 新增 Tomcat Server -> 选择 Local,Deployment 标签页点加号选择 war exploded,Application context 填项目上下文路径。
3.3 数据库初始化与配置文件核对:四个容易卡住的点
数据库初始化用 Navicat 或命令行都行。项目目录下通常有一个 .sql 文件,里面包含建库、建表、插入初始数据的完整语句。执行时先创建数据库,再导入表结构。这里有一个容易被忽略的问题:SQL 文件里有可能是多个数据库混写,导入前先确认当前选中的库对不对。
导入完成后,打开项目里 jdbc.properties 或者 db.properties 配置文件,核对以下四项:
jdbc.driver=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/attendance?useUnicode=true&characterEncoding=utf-8 jdbc.username=root jdbc.password=root数据库密码要和本机一致;数据库名称要和 SQL 脚本里创建的库名一致;如果你的 MySQL 是 8.0,驱动类名要改成 com.mysql.cj.jdbc.Driver;如果是 5.7,保持上面这个就行。URL 里的编码参数 characterEncoding=utf-8 必须保留,否则后面中文乱码处理起来很被动。
配置文件改完后启动 Tomcat,访问登录页。如果能看到登录框,说明基础链路已经通了。这一步走完,项目才算真正“活了”。后面的排查工作基本都集中在这四个环节——JDK 版本、Maven 仓库、数据库连接、上下文路径——任何一个不对,启动都会失败。
4. 核心业务串起来:签到、请假与审批的实现逻辑
4.1 Controller 入口:SignController 的职责划分
签到是这套系统的最高频操作,代码里对应的控制器是 SignController。从命名能看出它至少承担两个职责:发起签到和提交签到。下面是一个典型接口的结构:
@Controller @RequestMapping("/sign") public class SignController { @Autowired private SignService signService; // 教师发起签到:生成一条签到任务 @RequestMapping("/start") @ResponseBody public Map<String, Object> start(@RequestParam Integer courseId, @RequestParam Integer classId) { Map<String, Object> result = new HashMap<>(); SignTask task = new SignTask(); task.setCourseId(courseId); task.setClassId(classId); task.setStatus(1); // 1=进行中, 0=已结束 signService.createTask(task); result.put("code", 0); result.put("msg", "签到已发起"); return result; } // 学生提交签到:记录签到人、签到时间 @RequestMapping("/doSign") @ResponseBody public Map<String, Object> doSign(@RequestParam Integer taskId, @RequestParam Integer studentId) { Map<String, Object> result = new HashMap<>(); boolean ok = signService.doSign(taskId, studentId); result.put("code", ok ? 0 : 1); result.put("msg", ok ? "签到成功" : "签到失败,请确认签到任务存在"); return result; } }start 方法的逻辑是组装一个签到任务对象并写入表,status 字段标记当前任务是否进行中;doSign 方法接收任务 ID 和学生 ID,核心逻辑在 signService.doSign 里。一般 Service 层会先校验任务状态——只有进行中的任务才允许签到,然后检查学生是否属于该班级,最后插入签到记录。
这里要注意一个顺序问题:教师发起签到是“创建任务”,学生签到是“写入记录”,两者是分开的动作。如果把签到记录直接挂在教师发起的接口上,那就变成教师帮学生签到了,权限就乱了。代码里职责边界清晰,理解之后方便二次开发。
4.2 请假审批的状态流转:从提交到通过的完整链路
请假模块的状态流转比签到复杂一点,因为它涉及学生、辅导员、教师三个角色的协作。标准状态机是:0 待审批、1 已通过、2 已驳回。学生提交请假申请时默认状态为 0;辅导员查看列表后选择通过或驳回,状态变成 1 或 2;教师端查看请假列表时,按状态过滤展示。
这段逻辑在 Service 层通常长这样:
public int updateLeaveStatus(Integer leaveId, Integer status) { Leave leave = leaveMapper.selectById(leaveId); if (leave == null) { return 0; } // 校验当前状态,只有待审批的申请才能被审批 if (leave.getStatus() != 0) { return -1; // 已处理过,不能再操作 } leave.setStatus(status); return leaveMapper.update(leave); }这段代码里的关键点是那句话:只有 status 为 0 的记录才能被审批。如果不加这个判断,辅导员手滑点两次按钮会把“已通过”改成“已驳回”,历史数据就乱了。加上状态校验之后,审批操作变成幂等的,多次点击也不会产生脏数据。
还有一个容易被忽略的关联:请假通过后,教师端的签到统计里应该把该生标记为“请假”,而不是“缺勤”。很多初版项目不做这个关联,导致学生明明请了假,考勤报表里还是缺勤,这就很尴尬。拿到代码后建议先查一下请假表里是否有字段能关联到具体节次或日期,如果有的话把统计逻辑补上。
4.3 layui 前端与 JSP 的配合方式
前端用 layui 配合 JSP,属于典型的“半前后端分离”——页面由 JSP 渲染,交互逻辑由 layui 的模块驱动。layui 最常用的是 table 模块,后端返回 JSON 数据后,前端自动渲染成带分页、带搜索的表格。
layui.use(['table', 'layer'], function () { var table = layui.table; var layer = layui.layer; table.render({ elem: '#signTable', url: '/sign/list', page: true, cols: [[ { field: 'studentName', title: '学生姓名' }, { field: 'className', title: '班级' }, { field: 'signTime', title: '签到时间' }, { field: 'status', title: '状态', templet: function (d) { if (d.status === 1) return '正常'; if (d.status === 2) return '迟到'; return '缺勤'; }} ]] }); });这段代码的关键点是 url 参数——table 模块会向 /sign/list 发送请求,后端返回的 JSON 格式必须是 { code: 0, count: 总数, data: 列表 } 这种结构,否则表格渲染不出来。如果你发现页面表格一直转圈不显示,先打开浏览器控制台看接口返回的 JSON 结构。另外 templet 函数处理状态值的映射,把数字状态转成中文,用户看起来直观。
JSP 侧的工作主要是引入 layui 的 CSS 和 JS 文件,以及把登录用户的角色信息存在 session 里供前端判断显示哪些菜单。JSP 里写 Java 代码的方式虽然老派,但在这种规模的项目里效率很高,服务端渲染首屏数据,客户端负责交互,分工明确。
5. 避坑与常见问题:跑不起来时的排查顺序
5.1 Tomcat 启动直接报 ClassNotFoundException
现象:IDEA 启动 Tomcat 后控制台报错,提示找不到某个类,通常是 org.springframework.web.context.ContextLoaderListener。
原因:项目依赖没有完整部署到 Tomcat。IDEA 里运行 Tomcat 时,如果 Deployment 里选的是 war exploded,但 Artifacts 配置里的 lib 目录没有勾选“打包进 WEB-INF/lib”,所有 jar 包就不会被复制到运行目录。
解决:File -> Project Structure -> Artifacts,选中部署配置,双击右侧 Available Elements 里的 “Library Files”,让所有依赖加入打包。重新 Build 之后再启动 Tomcat。如果还不行,把原有的 Artifacts 删掉重新创建一个。
5.2 数据库连接失败:时区、驱动、密码三重因素
现象:启动时报 Communications link failure 或者 Access denied for user。
原因:优先排查三类问题——MySQL 服务没启动、用户名密码不匹配、连接串没带时区参数。如果是 MySQL 8.0,驱动类名和连接串都要更新,5.7 的配置直接套上去会报 SSL 或者时区错误。
解决:先执行 mysql -u root -p 确认账号密码;再确认驱动类名和 URL 是否与 MySQL 版本匹配;最后检查数据库名是否存在,导入 SQL 时有没有建库成功。用一个最简单的测试类分别执行 getConnection 验证。
5.3 页面能开但 CSS、JS、图片全部加载失败
现象:登录页能打开 HTML 结构,但完全没有样式,控制台一堆 404。
原因:Spring MVC 的 DispatcherServlet 把静态资源请求也拦截了,或者前端资源路径写的是绝对路径而不是带上下文路径的动态拼接,导致 Tomcat 找不到文件。
解决:检查 Spring MVC 配置文件中是否配置了静态资源放行,常见写法是<mvc:resources mapping="/static/**" location="/static/"/>;同时确保 JSP 里引用资源时用的是 ${pageContext.request.contextPath} 拼前缀,而不是写死 /css/xxx。两个问题解决一个就能恢复大部分样式。
5.4 中文乱码:请求参数和数据库返回全是问号
现象:页面上输入中文查询条件,后端起出来的数据里中文全是 ?? 或者乱码。
原因:多层编码问题叠加。请求层面是 Tomcat 默认 URI 编码不是 UTF-8;响应层面是 JSP 页面没有指定 UTF-8;数据库层面是连接串缺 characterEncoding=utf-8。
解决:三处同时改成 UTF-8。Tomcat 的 server.xml 里给 Connector 加 URIEncoding="UTF-8";每个 JSP 顶部确认 pageEncoding 和 content type 是 UTF-8;jdbc.properties 里连接串带上 useUnicode=true&characterEncoding=utf-8。缺一不可,只改一处会出现“一半正常一半乱码”的诡异现象。
5.5 Maven 依赖下载失败:卡在某个包一直报红
现象:pom.xml 里某个依赖一直报错,IDEA 提示 Cannot resolve symbol 或者说找不到 jar 包。
原因:默认中央仓库访问不稳定,或者本地仓库里残留了损坏的半成品文件. lastUpdated 后缀的临时文件会导致 Maven 认为依赖已存在但实际不可用。
解决:在 settings.xml 里配置阿里云镜像源,然后删除本地仓库里该依赖的所有目录,回到 IDEA 里点击 Reload All Maven Projects 强制重新下载。注意删除 lastUpdated 文件这步不能省,不删的话 Maven 不会重新拉取。
6. 进阶:把考勤数据变成可用的管理资产,而不只是一张表
6.1 出勤率统计:用一条 SQL 算出每个学生的缺席次数
项目跑通只是开始,真正能做加分的是把考勤数据变成统计报表。比如按学生维度统计缺勤次数,可以这样查:
SELECT s.id AS student_id, s.name AS student_name, COUNT(CASE WHEN r.status = 1 THEN 1 END) AS absence_count FROM student s LEFT JOIN sign_record r ON s.id = r.student_id WHERE r.status = 1 OR r.status IS NULL GROUP BY s.id, s.name HAVING absence_count > 0 ORDER BY absence_count DESC;status 为 1 表示缺勤,LEFT JOIN 保证那些没有任何签到记录的学生也会被统计出来,HAVING 过滤掉全勤学生。这条 SQL 可以直接做成一个导出接口,后端把查询结果写入 Excel 文件返回给前端下载,辅导员周期性导出发给学生。
6.2 从单学期到多学期:给日期字段加上学期维度
原版项目的签到记录表大概率只有一个 sign_date 字段,但考勤统计一旦跨学期,就必须有学期字段。我的做法是加一个 term_id 外键,在每次发起签到时从前端下拉框选中当前学期并写入。这样历史数据不会被新学期的统计污染,毕业季导出四年考勤汇总也能按学期切分。代码改动量不大,但整个系统的生命周期瞬间被拉长了。
这套项目我已经反复拆过好几次,每次跑都是先从环境校验开始,再到数据配置,最后才碰代码。从那以后我每次拿到新项目,都强制走一遍“日志起步、配置核对、权限穿透”这三步,不跳步,不猜。希望帮到你,祝你一次跑通。
本文还有配套的精品资源,点击获取