ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

基于SSM+Flask的学生考勤管理系统:从设计到部署

基于SSM+Flask的学生考勤管理系统:从设计到部署 每到学期中最让我头疼的其实是考勤。点名占用课堂时间纸质假条流转慢月底辅导员催出勤率催到崩溃学生偶尔还会代签。所以我一直觉得校园考勤这件事值得做得更系统一点。市面上有现成的考勤软件但部署在自己学校、按自己业务定制的方案不多。这篇文章分享的就是一套基于 Java SSM Flask 的学生考勤管理系统覆盖学生管理、课程排布、课堂签到、请假审批、出勤率统计与异常预警的完整闭环。我尽量把设计思路、数据库细节、核心代码片段、部署踩坑都摊开讲不管你是拿它做毕设、课程设计还是想参照着做一个团队内部考勤工具应该都能少走不少弯路。1. 项目定位这套考勤系统到底要解决什么问题1.1 校园考勤的真实痛点先别急着谈技术我接触过不少考勤类项目最大的问题是“为了做系统而做系统”。老师点名要用手机、辅导员统计要导表格、学生请假要交纸质单三个流程互相割裂数据口径还不一致。这套学生考勤管理系统要解决的就是把这几个环节串起来。老师可以在课堂上发起签到学生扫码或输入动态码完成考勤系统自动记录迟到、早退、缺勤状态学生请假走线上审批辅导员按班级、课程、时间段实时查看出勤率缺勤超过阈值的学生自动进入预警名单。很多做类似的 CRUD 系统容易忽略“异常处理”和“规则计算”。考勤系统的难点从来不是增删改查而是状态怎么定义、重复提交怎么拦截、出勤率用什么公式算、老师忘记签到了怎么办。这些我会在后面重点展开。1.2 系统角色与业务闭环一个完整的考勤系统角色不能太少否则流程闭环不成立。这套系统我按校园实际组织了四类角色管理员管理教师账号、学期课程、基础参数查看全校出勤概况。教师维护自己课程的上课学生发起签到处理请假申请。学生查看课表、完成签到、提交请假、查看个人出勤记录。辅导员或班主任查看所辖学生和班级的考勤统计接收缺勤预警。业务闭环可以简单理解成排课 → 上课发起签到 → 学生打卡 → 状态判定 → 请假补录 → 实时统计 → 异常预警。一套流程走完考勤数据就从课堂直接流到了统计报表里不再需要人为复制粘贴。1.3 为什么这个题目值得做从做项目的角度这个题材的性价比很高。它的业务模型清晰并不复杂但又有足够多值得深挖的点。你可以只做基础考勤也可以往二维码、定位、人脸识别、自动预警方向延展。技术栈上同时出现 Java 的 SSM 和 Python 的 Flask又正好戳中“双语言协作”这个亮点面试或答辩时很容易讲出东西。很多人拿到这种项目源码后第一件事就是启动然后截图代码逻辑反而不看。我更建议反过来先花半小时把数据库表结构看懂再跑通签到那条主链路之后每改一个功能你都知道动哪里。配套的 LW设计文档/毕业论文、调试文档、讲解视频的价值恰恰是在这里。2. 技术选型拆解SSM Flask 双引擎怎么分工2.1 SSM 和 Flask 各自扛什么活这套系统使用 SSMSpring SpringMVC MyBatis做主体业务Flask 做辅助业务。两个框架属于不同语言和生态但它们之间配合得非常自然。SSM 负责的是结构化、高并发、强一致性的业务比如登录鉴权、学生管理、课程管理、考勤记录写入、请假审批流。这些操作对事务要求高依赖 MyBatis 管理 SQL 和事务是合理选择。尤其是签到这种写操作多个人同时提交时必须保证状态不混乱。Flask 负责的是轻量、灵活、偏算法或偏文件处理的任务比如生成动态签到码、定时扫描缺勤数据、导出 Excel 报表、发送通知。Python 生态里做数据分析和定时任务非常顺手写起来比 Java 短很多。这里并不是“谁替代谁”而是让合适的工具出现在合适的场景里。2.2 双服务之间的通信与协作方式两个服务不是各自独立的孤岛它们通过 MySQL 共享数据再通过 HTTP 接口互相调用。常见做法是学生通过前端页面请求 Java 后端完成签到数据写入 MySQL。Flask 启动一个定时任务扫描考勤表中最近一段时间的数据统计各学生缺勤次数超过阈值就调用 Java 提供的通知接口或者直接向消息表写入记录。教师需要导出班级考勤表时前端请求 FlaskFlask 直接从数据库查询用 OpenPyXL 生成 Excel 文件返回。跨语言协作时接口边界要清晰。Java 端对外暴露的是用户认证和签到核心接口Flask 端暴露的是统计导出和通知辅助接口。两个服务共用同一个数据库但写入方向尽量单一避免多个服务同时改同一张表导致锁竞争。2.3 这样组合的价值在哪里很多人会问直接用 Spring Boot 全家桶不就好了也能做。但 Flask 在做数据统计、Excel 导出、告警推送这类“周边能力”时有天然优势代码量能少一半。反过来如果全部用 Flask 写事务管理、权限框架、企业部署又不如 Java 生态成熟。我自己的体会是双语言组合最重要的不是“炫技”而是让每个框架做自己顺手的那部分。Java 管核心数据稳Flask 管边缘功能快。两个服务通过接口和数据库协作彼此不纠缠后期想把 Flask 部分换成 Java 或者微服务也不会伤筋动骨。3. 功能设计与数据库建模3.1 功能清单与角色权限无论项目大小权限都必须从第一天就设计清楚。我用的是经典的 RBAC 模型用户表、角色表、用户角色关联表再加上菜单或接口权限点。系统基础功能可以拆成这几块学生管理班级维护、新生导入、学生信息查询、账号启停用。课程管理课程开设、教师任课、选课名单管理。考勤管理发起签到、学生打卡、自动判定状态、手工补卡、请假记录。统计报表按课程、班级、个人多维度查看出勤率导出 Excel。预警通知缺勤次数异常提醒、辅导员站内信通知。我建议你实际操作时先画出每个角色能访问的页面和按钮再建表。前端权限可以先做按钮级控制后端接口也做拦截不然随便一个学生通过接口就能把自己改成已签到后期非常被动。3.2 考勤表设计别让状态字段失控考勤系统的核心表不多但每一张表都得认真设计。我重点说说考勤记录表。学生出勤状态我定义为正常、迟到、早退、缺勤、请假五个状态。数据库里不要直接存中文用枚举值 1、2、3、4、5展示层再映射回文字。这样可以避免排序和统计时出现字符串比较的坑。考勤记录表至少应该有这些字段字段说明id主键student_id学生 IDcourse_id课程 IDattendance_date考勤日期course_time上课时间段第几节或具体时间status状态枚举1正常 2迟到 3早退 4缺勤 5请假sign_time实际签到时间sign_type签到方式1动态码 2二维码 3补录remark备注信息这里有两个关键设计第一表里要加唯一索引比如(student_id, course_id, attendance_date, course_time)防止学生重复签到绕过业务判断。数据库层兜底永远比应用层判断更可靠。第二状态不要靠“翻转”来改如果老师发现学生迟到改成了正常最好保留一条修改日志。单独弄一张考勤变更记录表或者至少在 remark 里写清楚原因否则后期核对数据时说不清楚。3.3 出勤率计算规则与案例分析出勤率看似简单最容易翻车的是分母怎么算。我见过不少项目直接把“应出勤次数”算成课程总数但学生可能中途转班、请假获批不计缺勤这些都会导致分母失真。我采用的口径是应出勤次数 当前课程已进行的考勤次数 - 已批准请假的次数。实际出勤次数 正常 迟到 早退其中迟到和早退按已出勤计入。出勤率 实际出勤次数 / 应出勤次数 × 100%。举个例子一门课这学期已发起 10 次签到某学生请假获批 2 次剩余应出勤 8 次其中正常 5 次、迟到 1 次、缺勤 2 次那出勤率就是 (51)/8 75%。如果请假也当缺勤学生会很吃亏统计口径必须明确写进文档。统计 SQL 写起来不复杂但要考虑 MySQL 的日期函数和分组例如SELECT course_id, COUNT(*) AS total_count, SUM(CASE WHEN status IN (1,2,3) THEN 1 ELSE 0 END) AS actual_count, ROUND(SUM(CASE WHEN status IN (1,2,3) THEN 1 ELSE 0 END) / COUNT(*) * 100, 2) AS attendance_rate FROM attendance_record WHERE attendance_date BETWEEN ? AND ? GROUP BY course_id;注意这个查询没有排除请假如果采用“请假不计入分母”的口径需要先统计请假次数或者先通过子查询过滤。4. 关键模块实操签到、统计、预警一条链4.1 动态签到码与防代签设计传统口令点名很容易代答二维码又容易被分享出去。我用的是“动态签到码 有效期 移动端定位范围约束”组合方案。流程上教师点击发起签到请求 Flask 生成一个随机的 6 位数字码和过期时间比如 120 秒同时写入 Redis 或内存缓存。学生端输入签到码并携带自己的经纬度提交到 Java 端。Java 端先校验签到码是否存在且未过期再校验学生的定位与教师预设的教室位置距离是否小于阈值通过后写入考勤记录。这里最容易被忽略的是迟到判定。签到码过期后教师可以再次发起补签或者允许学生在规定时间内提交但状态需要自动变成“迟到”。比如签到码有效 2 分钟期间签到的算正常课程开始后 15 分钟内签到的算迟到超过 15 分钟未签到的系统在课程结束时自动写入缺勤。防代签不能只靠距离GPS 定位可以被模拟。有条件的话可以增加设备指纹或者对接校园网 IP 白名单。项目演示阶段用定位即可真正落地再叠加设备特征。4.2 出勤统计与 Excel 报表导出统计功能要同时满足“老师看自己班的”“辅导员看整个学院的”两种视角。一般做法是先把基础数据查出来再按维度分组汇总。我给出的统计接口思路是入参角色、用户 ID、课程 ID、班级 ID、开始日期、结束日期。查出考勤明细数据按学生分组。对每个学生统计总次数、各状态次数、出勤率。按出勤率升序排列让预警名单自然浮在最前面。Excel 导出交给我推荐的 Flask 来做底层库可以用 OpenPyXL。代码比 Java 的 POI 简洁很多from openpyxl import Workbook def export_attendance(students): wb Workbook() ws wb.active ws.append([学号, 姓名, 班级, 出勤次数, 迟到, 早退, 缺勤, 出勤率]) for stu in students: ws.append([stu[student_no], stu[name], stu[class_name], stu[actual_count], stu[late_count], stu[early_count], stu[absent_count], f{stu[rate]}%]) wb.save(attendance.xlsx) return attendance.xlsx导出的文件不要直接放在本地磁盘的某个固定路径上我用/tmp目录或者 MinIO/OSS 之类对象存储返回一个下载链接。否则部署在 Linux 服务器上路径权限问题会折腾很久。4.3 缺勤预警与消息通知预警是让考勤系统“活”起来的核心功能。我用 Flask 里的定时任务实现了一个轮询扫描数据每 30 分钟检查一次最近 7 天内有缺勤记录且缺勤次数达到阈值的在校学生然后写一条待处理预警到数据库并推送站内信给该生对应的辅导员。预警规则不要写死在代码里。我建了一张规则表每个班或学院可以配置不同阈值比如一周内缺勤满 3 次触发预警、请假未及时补录触发提醒。这样系统交给不同老师使用时不用二次开发。通知方式分三层站内信写进 message 表用户登录后红点提示。邮件适合通知到学院负责人用 Flask 的 SMTP 库发送。短信项目演示阶段多数不接真实短信服务我建议先做接口预留等真正需要时再对接阿里云或腾讯云短信。站内信最重要的是“已读状态”和“跳转链接”。用户点开一条预警最好直接跳到对应的考勤明细页而不是只看到一条文字记录。4.4 双端联调代码示例SSM Flask下面放一段核心的签到接口示例帮你理解 Java 端怎么接收学生请求并做状态判断。RestController RequestMapping(/attendance) public class AttendanceController { Autowired private AttendanceService attendanceService; PostMapping(/sign) public Result sign(RequestBody SignRequest req) { // req: studentId, courseId, signCode, latitude, longitude boolean valid attendanceService.checkCode(req.getSignCode()); if (!valid) { return Result.error(签到码无效或已过期); } int status attendanceService.calcStatus(req, new Date()); attendanceService.saveRecord(req.getStudentId(), req.getCourseId(), status, new Date()); return Result.success(签到成功); } }实际上这里的checkCode应该去查共享的 Redis签到码是在 Flask 里生成的两边要约定好 Redis key 的命名规则比如sign:code:{courseId}:{date}这样互相不会覆盖。Flask 侧的定时任务和签到码生成可以这样组织import random from flask import Blueprint, jsonify import pymysql sign_bp Blueprint(sign, __name__) # 生成签到码 def generate_sign_code(course_id, expire_seconds120): code str(random.randint(100000, 999999)) # 存入共享缓存键名与 Java 约定一致 cache.set(fsign:code:{course_id}, code, exexpire_seconds) return code # 扫描缺勤预警 def scan_absent_alert(): conn pymysql.connect(hostlocalhost, userroot, passwordpassword, databaseattendance_db) cursor conn.cursor() sql SELECT student_id, COUNT(*) AS cnt FROM attendance_record WHERE status 4 AND attendance_date DATE_SUB(NOW(), INTERVAL 7 DAY) GROUP BY student_id HAVING cnt 3 cursor.execute(sql) for student_id, cnt in cursor.fetchall(): insert_message(student_id, 缺勤预警, f近7天缺勤{cnt}次请及时处理) conn.close()这种代码结构很清晰Java 和 Python 各管一段。你复制到自己的项目里时重点检查数据库连接和 Redis 配置是否和实际环境一致。5. 部署落地与问题排查5.1 环境准备与打包部署部署这套系统你需要准备这些基础环境JDK 8 或 11本地开发建议版本保持一致避免编译问题。Tomcat 8 以上SSM 项目打 WAR 包部署。MySQL 5.7 或 8.0初始化 SQL 脚本先执行。Python 3.8 以上Flask 及第三方库安装到虚拟环境。SSM 项目打包时需要注意pom.xml里如果依赖了spring-boot-maven-plugin它打出来的可能是可执行 JAR。纯 SSM 项目不要用这个插件直接打mvn clean package生成 WAR。WAR 放到 Tomcat 的webapps目录后会自动解压启动后访问/attendance-web/这样的应用路径来确认。Flask 服务建议用 Gunicorn 启动不要直接用python app.py跑pip install gunicorn gunicorn -w 2 -b 127.0.0.1:5000 app:app生产环境我习惯在前面挂 Nginx将/flask-api/路径代理到 Flask其余路径代理到 Tomcat。这样前端可以避免跨域也方便统一管理静态资源。5.2 常见问题与排查速查表我在实际调试这类项目时遇到最多的不是大功能失败而是一些环境层面的小问题。整理成一张速查表方便你对照。问题现象原因解决方法页面中文乱码数据库或 Tomcat 编码不一致建库时指定 utf8mb4JDBC 连接串加 useUnicodetruecharacterEncodingutf8MySQL 连接报时区错误Connector/J 8.0 要求 serverTimezoneJDBC 连接加 serverTimezoneAsia/ShanghaiJava 和 Flask 数据不同步两边用了不同数据库实例检查 application.yml 和 Flask 的 config 是否指向同一个库签到码生成后 Java 校验失败Redis key 规则不一致统一使用 sign:code:{courseId}:{date}前端请求 Flask 接口报跨域前后端端口不同用 Nginx 反向代理同域或启用 CORS导出 Excel 乱码OpenPyXL 与 Excel 编码兼容问题文件名用 ASCII内容统一 UTF-8打包后看不到上传的图片本地路径和服务器路径不一致静态资源单独配置虚拟路径映射5.3 性能与安全上的几个注意点考勤系统并发量并不会特别高但签到瞬间会有几十人同时提交请求。我建议你在 Java 端签到接口添加事务控制并且对同一个学生的重复请求做幂等处理。最简单的方式就是先插一条临时记录唯一索引冲突时捕获异常不要让学生看“白屏卡住”。安全上有三类问题必须处理接口鉴权不能只靠前端隐藏按钮所有接口都要校验 Token。SSM 用拦截器统一处理Flask 用装饰器做鉴权两边的 Token 发放统一走 Java 端。密码必须加密存储推荐 BCrypt不要用 MD5 加盐这种老方案。签到码接口要加频率限制比如同一 IP 每分钟最多请求 5 次防止脚本刷码。Flask 端写一个简单的内存计数器即可真上了生产再考虑 Redis 计数。数据备份也很重要。每天早上用 cron 跑一次mysqldump把考勤记录表单独备份出来。毕竟考勤数据一旦丢了相当于整学期记录全废补数据是极其痛苦的过程。这一条建议是很多项目的共性问题建议你提前做。6. 后续扩展玩法这个项目给我最大的惊喜是扩展性很强。如果你交完项目还想继续玩我列几个方向供参考人脸签到替换动态码用 Flask 接收图片调用百度 AI 或本地 OpenCV 人脸比对识别结果回传给 Java 写入考勤记录。前提是提前采集学生照片并建立特征库。出勤数据可视化Flask 提供数据聚合接口前端用 ECharts 展示缺勤率趋势图、迟到高峰时段、各班级横向对比表达效果比表格好很多。自动生成辅导员周报每周五定时把各班出勤率统计成 PDF 或 Excel通过邮件发给对应老师。用 Python 的 reportlab 就能实现。对接课表系统如果学校有自己的课表系统可以定时同步课程安排考勤发起不再需要老师手动选课。这些扩展不一定都要做挑一个你感兴趣的做透整套系统的层次会比单纯“管理页面”高不少。最后补充一点我个人特别深的体会考勤系统的核心不是代码多花哨而是状态节点要清晰、数据口径要统一。哪怕只有十几张表只要把“谁、什么课、哪天、什么状态”这条主链路跑顺系统已经能解决大部分现实问题。做项目时别急着追求新技术堆砌先把核心链路打通再谈扩展。这套 SSM Flask 的组合对我来说就是“核心链路足够稳、周边功能足够活”的典型例子这也是我特别推荐的原因。
返回列表