尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

人脸识别+JSP+SQL Server:学生考勤管理系统全解析

人脸识别+JSP+SQL Server:学生考勤管理系统全解析 简介面向高校计算机专业学生及毕业设计开发者这份基于人脸识别的学生签到考勤管理系统设计文档围绕请假、考勤、后台管理三大核心模块展开覆盖学生、任课老师、班级辅导员、部门负责人、学校负责人及系统管理员六类角色旨在解决传统课堂考勤效率低、代签频发等问题。文档基于JSPSQL Server 2000完成技术选型结合人脸识别技术实现签到管理并详细展示了数据库E-R图、数据字典、UML用例分析及登录界面等关键设计环节从需求分析、可行性研究到数据库设计与功能实现均有系统论述。压缩包内包含1个docx文档约369KB内容结构完整可作为课题设计、论文撰写或技术实现的参考底稿。目前已有138人学习下载适合正在准备相关考勤系统项目的读者快速把握整体方案。1. 从“点名”到“人脸签到”的价值重构传统课堂点名消耗的时间与准确率之间的冲突是每个高校教务管理者都绕不开的痛点。人工点名在百人阶梯教室中不仅耗时 5 到 10 分钟还无法杜绝代答、漏报期末统计出勤数据更是需要班委和辅导员反复核对 Excel 表。基于人脸识别的学生签到考勤管理系统把身份核验从“听到应答”变成“看到人脸”在前后端分离的 Web 架构下完成在线请假审批、课程表联动、出勤数据自动汇总与多级角色权限控制。对开发者的价值在于这个项目完整展示了 JSP 传统 Web 应用如何与现代人脸识别 API 结合、如何设计多角色权限模型、以及如何在 SQL Server 2000 这类老牌关系型数据库上做表结构规划。无论是准备课程设计、毕业设计还是想在自己学校的信息化系统中落地一套考勤模块这个项目的拆分思路都值得参考。2. 系统角色模型与功能矩阵设计2.1 六类角色的权限边界系统涉及六个用户角色学生、任课老师、班主任、院系负责人、学校负责人、系统管理员。在设计权限时不能只靠一个role字段做硬编码因为同一个人可能既是任课老师又是班主任甚至兼任部门负责人。我在拆分项目时采用“角色-功能”映射表用user_role和role_menu两张表维护动态权限而不是在 JSP 页面里写死if (role.equals(teacher))。角色功能矩阵如下功能模块学生任课老师班主任院系负责人学校负责人系统管理员查看课程表是是是是是是在线请假申请是否否否否否审批请假≤3天否否是否否否审批请假3天否否是是否否录入/修改考勤否是是否否否查看统计报表否否是是是是系统基础数据维护否否否否否是这张矩阵直接对应数据库中的role_id和menu_id关联表。JSP 页面在渲染菜单时通过session.getAttribute(menus)获取当前角色可访问的菜单列表未授权的菜单不会出现在界面上。这样做的好处是后续学校要增加“辅导员助理”角色时只需要往角色表和菜单关联表插入数据无需改动页面逻辑。2.2 请假流程的状态机设计请假审批是系统中业务逻辑最密集的部分。原文明确要求学生请假超过三天含必须经过班主任批准后再提交部门负责人审批。这实际上是两级审批状态机待审批班主任 - 班主任通过 - 待审批部门 - 部门通过 - 生效 | | ---- 班主任驳回 ------------------- 部门驳回 | | 最终状态 最终状态在数据库T_qingjiadan表中用shenhe字段记录当前状态。我建议使用整数状态码而不是中文字符串因为字符串排序和索引性能差。状态码定义如下-- 状态码说明 -- 0草稿学生保存未提交 -- 1待班主任审批 -- 2班主任已通过待部门审批仅请假时长3天 -- 3审批完成请假生效 -- 4班主任驳回 -- 5部门驳回审批过程中必须校验时间冲突学生不能在同一时间段重复请假系统要查询T_qingjiadan中同用户名下是否存在qjtime2 新请假开始时间且qjtime1 新请假结束时间的生效记录。实际开发中这个查询经常被遗漏。3. 数据库物理设计与关键实现3.1 SQL Server 2000 下的表结构落地虽然 SQL Server 2000 年代久远但它的范式设计和事务机制对考勤这类业务仍然够用。项目中的核心表包括T_user用户、T_banji班级、T_kecheng课程、T_kaoqinlog考勤记录、T_qingjiadan请假单、T_subject科目。下面是重构后的建表语句我加了索引和约束这是原项目描述里没有细化的部分CREATE TABLE T_user ( id INT PRIMARY KEY IDENTITY(1,1), username VARCHAR(20) NOT NULL UNIQUE, password VARCHAR(32) NOT NULL, role TINYINT NOT NULL DEFAULT 1, -- 1学生 2任课老师 3班主任 4院系负责人 5学校负责人 6管理员 banjinum VARCHAR(8) NULL, -- 班级编号 codenum VARCHAR(10) NULL, -- 学号/工号 phone VARCHAR(20) NULL, address VARCHAR(50) NULL, room VARCHAR(10) NULL, userlock VARCHAR(1) DEFAULT 0 -- 0正常 1锁定 ); CREATE TABLE T_kaoqinlog ( id INT PRIMARY KEY IDENTITY(1,1), banjiname VARCHAR(20) NOT NULL, banjinum VARCHAR(8) NOT NULL, kechengname VARCHAR(20) NOT NULL, kuangkenum VARCHAR(20) NOT NULL, -- 旷课学生学号逗号分隔 iskuangke VARCHAR(10) NOT NULL, -- Y/N 是否全勤 teacher VARCHAR(20) NOT NULL, createtime DATETIME DEFAULT GETDATE() );注意kuangkenum字段用逗号分隔学号保存旷课名单这是典型的“反范式”设计。好处是查询某一节课的出勤状态时只需一次 LIKE 查询坏处是统计某学生总旷课次数时需要用CHARINDEX逐条判断。在数据量小于 10 万条的校园考勤场景下这个设计可以接受而且便于老师直接复制名单到 Excel。3.2 考勤记录的业务规则考勤记录和请假申请之间存在强约束如果某学生在课程当天请假成功系统自动将该生的课堂出勤记录登记为“请假”任课老师提交考勤时不能把这个学生标记为旷课。实现这个规则的关键是写一个存储过程在插入T_kaoqinlog之前检查请假表CREATE PROCEDURE sp_check_leave stu_code VARCHAR(10), course_date DATETIME AS BEGIN SELECT COUNT(*) AS leave_count FROM T_qingjiadan WHERE username stu_code AND shenhe 3 AND course_date BETWEEN CONVERT(DATETIME, qjtime1) AND CONVERT(DATETIME, qjtime2); END在 JSP 端调用这个存储过程后如果返回leave_count 0则在插入考勤记录时跳过该学生或者单独标记为iskuangke L。我在实际项目中遇到过一个问题老师提前一个月录入补考勤而请假单是事后补的导致冲突。解决办法是提交考勤的时间必须限定在课程结束后 7 天以内超过期限需要管理员授权。4. 人脸识别能力与 JSP 前端集成4.1 百度人脸识别接口的调用模式项目描述中明确提到“调用百度的识别算法的接口去实现了人脸检测的目的”。百度 AI 开放平台的人脸检测接口是https://aip.baidubce.com/rest/2.0/face/v3/detect需要先获取access_token。旧版 JSP 项目里没有 Spring RestTemplate通常用HttpURLConnection或者 Apache HttpClient 4.x 发送 JSON 请求。前端通过浏览器摄像头采集人脸照片JSP 页面用 Canvas 将视频帧转为 Base64再提交到后端FaceServlet。核心代码如下// detect.jsp 中采集人脸帧 const video document.getElementById(video); const canvas document.createElement(canvas); const ctx canvas.getContext(2d); function captureFace() { canvas.width 480; canvas.height 360; ctx.drawImage(video, 0, 0, 480, 360); const base64 canvas.toDataURL(image/jpeg, 0.8).split(,)[1]; fetch(/attendance/FaceServlet, { method: POST, headers: { Content-Type: application/x-www-form-urlencoded }, body: image encodeURIComponent(base64) typedetect }) .then(res res.json()) .then(data { if (data.face_num 0) { document.getElementById(result).innerText 人脸检测成功; } else { document.getElementById(result).innerText 未检测到人脸请正对摄像头; } }); }FaceServlet端根据前端传来的type参数分发到不同逻辑detect代表签到前的活体检测register代表新生人脸信息录入。服务端用一个FaceClient类封装百度 API 调用避免每个 Servlet 重复写 HTTP 连接代码。4.2 人脸特征值存储与匹配策略百度人脸识别接口支持在百度云人脸库中直接创建用户组和添加人脸也可以只调用“人脸检测”与“人脸搜索”能力自己管理特征值。校园场景中我倾向于使用百度云人脸库因为学校网络环境复杂自己存特征 FaceID 会导致数据库字段过长且无法跨平台迁移。调用人脸搜索的代码// FaceClient.java 部分实现 public JSONObject faceSearch(String faceBase64, String groupId) { String url https://aip.baidubce.com/rest/2.0/face/v3/search; JSONObject param new JSONObject(); param.put(image, faceBase64); param.put(image_type, BASE64); param.put(group_id, groupId); param.put(liveness_control, NORMAL); // 活体检测等级 String result HttpClientUtil.postJson(url, param.toString(), accessToken); return JSONObject.parseObject(result); }实际部署时需要注意liveness_control参数有三个取值NONE、LOW、NORMAL、HIGH。课堂签到环境光线不稳定人脸偶尔被书本遮挡设置HIGH会导致大量误拒。我一般推荐使用NORMAL并在前端提示学生摘下口罩、露出额头。匹配阈值face_score通常设在 80 分以上如果低于该分数系统返回“身份不确定”需要转人工确认。4.3 静态 JSP 页面与前端动态渲染传统 JSP 开发中页面模块化通常用% include fileheader.jsp %引入公共头部。这个项目里我建议把菜单、用户信息栏、底部版权都抽成独立 JSP 片段。课程表查询页面通过 AJAX 请求CourseServlet后端返回 JSON 数组再用 JavaScript 动态拼接到表格中function loadCourseTable(banjinum) { $.ajax({ url: /attendance/CourseServlet, data: { banjinum: banjinum }, dataType: json, success: function (data) { let rows ; for (let i 0; i data.length; i) { rows trtd data[i].kechengname /td td data[i].teacher /td td data[i].weekday /td/tr; } $(#courseTable tbody).html(rows); } }); }注意 JSP 2.0 之前的版本本身不支持 EL 表达式和 JSTL 简捷迭代如果是在 SQL Server 2000 时代的 Tomcat 5.5 上运行只能通过% for %脚本片段输出。比较稳妥的做法是引入 JSTL 1.2 标签库用c:forEach遍历课程列表维护成本低很多。5. 部署排错与人脸识别签到的实用技巧5.1 SQL Server 2000 连接的 JDBC 驱动配置项目使用 SQL Server 2000JDBC 驱动需要用 Microsoft 的mssqlserver.jar连接 URL 格式是jdbc:microsoft:sqlserver://localhost:1433;DatabaseNameattendance这与 SQL Server 2008 之后的jdbc:sqlserver://不同。引入驱动后必须把Driver类名写为com.microsoft.jdbc.sqlserver.SQLServerDriver很多初学者会写错成com.microsoft.sqlserver.jdbc.SQLServerDriver这是导致ClassNotFoundException的常见原因。Tomcat 中配置数据源时需要把驱动 jar 放到%TOMCAT_HOME%/common/lib而不是WEB-INF/lib否则 JNDI 数据源无法加载。如果你用的是 Tomcat 6 及以上版本建议直接使用 JNDI 数据源避免在每个 Servlet 中重复建立连接。配置示例Context Resource namejdbc/attendanceDS authContainer typejavax.sql.DataSource maxActive20 maxIdle10 maxWait10000 driverClassNamecom.microsoft.jdbc.sqlserver.SQLServerDriver urljdbc:microsoft:sqlserver://127.0.0.1:1433;DatabaseNameattendance usernamesa passwordyour_password/ /Context部署完成后用http://localhost:8080/manager/html检查 Tomcat 数据源状态如果出现Cannot create JDBC driver of class com.microsoft.jdbc.sqlserver.SQLServerDriver说明驱动版本与数据库位数不匹配更换为 SQL Server 2000 对应 jdbc 驱动即可。5.2 人脸签到并发场景下的性能调优一个 300 人的阶梯教室在下课瞬间同时提交人脸识别请求如果所有请求都同步走百度云端识别公网带宽瓶颈会非常明显。我的处理方式是在后端加一层LinkedBlockingQueue做异步缓冲前端只提示“识别请求已接收”后台队列顺序消费请求并回写结果。可以在web.xml中配置一个ServletContextListener启动消费线程代码示意public class FaceQueueListener implements ServletContextListener { private BlockingQueueString queue new LinkedBlockingQueue(500); Override public void contextInitialized(ServletContextEvent sce) { for (int i 0; i 3; i) { new Thread(() - { while (true) { try { String base64 queue.take(); FaceClient.searchAndRecord(base64); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } }).start(); } } }队列容量设置为 500超出的请求直接拒绝并提示学生 3 秒后重试。这样避免了 Tomcat HTTP 线程被百度接口的慢响应占满也保证了考勤记录不会因为网络抖动丢失。此外签到高峰期前 10 分钟预热百度 access_token使用expires_in提前 5 分钟自动刷新避免首次请求因获取 token 而增加 200ms 延迟。5.3 常见异常排查清单在部署过程中我总结出三个优先级最高的坑第一人脸识别返回error_code: 222202含义是图片质量差通常是光线过暗导致。解决办法是禁止前置摄像头夜间模式在拍照前设置video.style.filter brightness(1.2)并在前端提示“请面向光源”。第二SQL Server 2000 中DATETIME字段存储日期时如果 JSP 端用SimpleDateFormat(yyyy-MM-dd)解析后直接拼入 SQL 语句会因默认语言设置不同导致Conversion failed异常。建议统一使用PreparedStatement.setTimestamp()不要用字符串拼接。第三用户登录后 session 失效时间过短。Tomcat 默认 30 分钟学生签到时排队等待会导致后台 session 过期。在web.xml中设置session-configsession-timeout120/session-timeout/session-config同时在人脸识别请求中带上keepSessiontrue参数每次识别成功后重置 session 活跃时间这样整个签到流程结束前不会掉线。本文还有配套的精品资源点击获取
返回列表