SSM+MySQL查寝打卡小程序源码拆解:从环境搭建到二次开发 简介这是一套面向高校计算机相关专业学生的查寝打卡微信小程序毕业设计源码采用JavaSSM框架开发服务端小程序端基于uniapp或原生小程序实现数据库使用MySQL 5.7适合作为毕业设计、课程设计或小程序入门练手项目。功能覆盖学生注册、通知公告、课程表查看、寝室签到获取位置并上传自拍、事假病假申请与考勤查询教师端则提供管理员、课程表、学生信息、通知公告、签到审核、请假与考勤统计等管理模块前后端逻辑完整。压缩包共342个文件约34.77MB包含33个java源文件、37个class、59个jar依赖以及wxml、wxss、js、json等小程序页面文件另有sql脚本、说明文档与LW论文结构清晰便于二次开发。目前已有71人学习下载可帮助读者快速理解签到定位、图片上传与人工审核等业务实现并直接用于答辩演示或功能扩展。1. 查寝打卡小程序一份能跑通的 SSM MySQL 前后端源码拆解每年毕业季查寝打卡类小程序都是课程设计和毕业设计里的高频选题。原因很直接业务闭环清晰学生端要签到、请假、看考勤教师端要审核、统计、管课程前后端都能写出东西答辩时也容易讲清楚。但真正动手时很多人卡在同一个地方——网上找到的源码要么只有前端页面要么后端接口对不上数据库表结构还缺字段跑起来一堆红字。这份资源是一套完整的查寝打卡微信小程序源码后端用 Java SSM 框架数据库 MySQL 5.7小程序端支持 uniapp 或原生开发附带说明文档和论文材料。学生端覆盖注册、通知公告、课程表、寝室签到含位置信息和自拍照片上传、请假、考勤查看教师端覆盖管理员信息、课程表、学生信息、通知公告、签到审核、请假管理和考勤统计。如果你正在做类似选题或者想找一套能跑通的前后端分离项目练手这套东西的完整度是够的。2. 环境搭建与项目导入从 JDK 到 Tomcat 的完整链路2.1 后端环境选型与版本对齐这套源码的技术栈是 SSMSpring SpringMVC MyBatis服务器指定 Tomcat 7JDK 版本 1.8数据库 MySQL 5.7开发工具支持 Eclipse 或 IDEA。这几个版本不是随便写的Tomcat 7 对 Servlet 3.0 的支持和 SSM 的 XML 配置方式匹配度最高JDK 1.8 则是 SSM 生态里兼容性最稳的版本。如果你用 JDK 11 或 Tomcat 9大概率会在启动时遇到ClassNotFoundException或者NoSuchMethodError这不是代码问题是版本错配。我一般会先把环境锁死再导入项目避免后面排查时分不清是代码问题还是环境问题。具体操作顺序如下# 1. 确认 JDK 版本 java -version # 期望输出java version 1.8.0_xxx # 2. 确认 MySQL 版本 mysql --version # 期望输出mysql Ver 14.14 Distrib 5.7.xx # 3. 确认 Tomcat 版本 # 查看 Tomcat 安装目录下 RELEASE-NOTES 文件 cat $TOMCAT_HOME/RELEASE-NOTES | head -5 # 期望输出包含Apache Tomcat Version 7.0.xx这三条命令看起来简单但血泪经验是很多人直接跳过版本确认导入项目后启动报错然后花几个小时去查代码最后发现是 JDK 版本不对。先把版本对齐后面能省掉一半的排查时间。2.2 数据库导入与连接配置数据库是这套项目的核心表结构设计直接决定了签到、请假、考勤统计能不能正常跑。源码包里一般会有一个.sql文件用 Navicat 11 或者命令行导入都可以。导入之前先建库字符集用utf8mb4不然学生姓名里的生僻字或者自拍照片的路径可能会乱码。-- 创建数据库字符集必须用 utf8mb4 CREATE DATABASE dorm_check DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; -- 导入表结构假设 sql 文件名为 dorm_check.sql USE dorm_check; SOURCE /path/to/dorm_check.sql; -- 导入后检查核心表是否存在 SHOW TABLES; -- 期望看到student、teacher、attendance、leave_record、course、notice 等表导入完成后需要修改后端配置文件里的数据库连接信息。SSM 项目一般会在jdbc.properties或applicationContext.xml里配置数据源。重点检查三个参数jdbc.url、jdbc.username、jdbc.password。URL 里要带上useUnicodetruecharacterEncodingutf8否则中文通知公告会变成问号。# jdbc.properties 关键配置 jdbc.drivercom.mysql.jdbc.Driver jdbc.urljdbc:mysql://localhost:3306/dorm_check?useUnicodetruecharacterEncodingutf8useSSLfalse jdbc.usernameroot jdbc.password你的密码提示MySQL 5.7 的驱动类名是com.mysql.jdbc.Driver如果你用的是 MySQL 8.x驱动类名要改成com.mysql.cj.jdbc.DriverURL 也要加时区参数。这套源码指定的是 5.7建议不要混用。2.3 项目导入 IDEA 与 Tomcat 配置Eclipse 和 IDEA 都支持但我更推荐 IDEA因为 Maven 依赖管理和 Tomcat 配置更直观。导入时选择Import Project指向源码根目录如果是 Maven 项目就选 Maven如果是普通 Web 项目就选 Eclipse 或 Web Application。导入后检查pom.xml里的依赖是否完整重点看spring-webmvc、mybatis、mysql-connector-java、javax.servlet-api这几个。如果依赖下载失败换阿里云镜像源。!-- pom.xml 中需要确认的核心依赖 -- dependency groupIdorg.springframework/groupId artifactIdspring-webmvc/artifactId version4.3.xx/version !-- 版本以源码为准 -- /dependency dependency groupIdorg.mybatis/groupId artifactIdmybatis/artifactId version3.4.xx/version /dependency dependency groupIdmysql/groupId artifactIdmysql-connector-java/artifactId version5.1.xx/version /dependencyTomcat 配置时Deployment 里要添加war exploded或者war包Application context 建议设为/或/dorm。启动后访问http://localhost:8080/看是否能进入登录页。如果报 404检查web.xml里的DispatcherServlet映射路径和 SpringMVC 配置文件的位置。3. 学生端核心功能实现签到、请假与考勤查看3.1 寝室签到位置获取与自拍上传的接口对接学生签到是这套项目里技术点最密集的模块。流程是学生进入签到页 → 获取当前定位 → 拍照或选图 → 提交签到请求 → 后端保存位置坐标和图片路径 → 教师端人工审核。小程序端获取位置用uni.getLocation拍照用uni.chooseImage上传用uni.uploadFile。// 小程序端签到核心逻辑uniapp 写法 uni.getLocation({ type: gcj02, // 微信小程序必须用 gcj02 success: (res) { const latitude res.latitude; const longitude res.longitude; // 拍照或选图 uni.chooseImage({ count: 1, sourceType: [camera], // 强制拍照防止相册选旧图 success: (imgRes) { const tempFilePath imgRes.tempFilePaths[0]; // 上传图片和位置信息 uni.uploadFile({ url: http://你的后端地址/attendance/checkIn, filePath: tempFilePath, name: file, formData: { latitude: latitude, longitude: longitude, studentId: 当前学生ID }, success: (uploadRes) { console.log(签到提交成功, uploadRes.data); } }); } }); } });后端接收时AttendanceController会处理/attendance/checkIn请求保存位置和图片路径到attendance表。这里有个关键参数sourceType设为[camera]是为了防止学生从相册选一张以前拍的照片来糊弄签到。教师端审核时会同时看到位置坐标和自拍照片人工判断是不是本人、位置对不对。注意微信小程序获取位置需要在manifest.json里配置requiredPrivateInfos和权限声明否则uni.getLocation会直接失败。这是很多新手翻车的地方代码没问题是配置没加。3.2 请假流程事假病假的状态流转请假模块的业务逻辑比签到复杂因为涉及状态流转。学生提交请假申请选事假或病假填开始结束时间、原因后端插入leave_record表状态为“待审核”。教师端看到申请后审核通过或驳回状态变为“已通过”或“已驳回”。学生端“我的考勤”里能看到请假记录和当前状态。// LeaveController 核心方法示意 RequestMapping(/leave/apply) ResponseBody public MapString, Object applyLeave(RequestBody LeaveRecord record) { MapString, Object result new HashMap(); // 参数校验请假类型、时间范围、原因不能为空 if (record.getType() null || record.getStartTime() null) { result.put(code, 400); result.put(msg, 请假类型和时间不能为空); return result; } // 设置初始状态为待审核 record.setStatus(待审核); record.setCreateTime(new Date()); leaveService.insert(record); result.put(code, 200); result.put(msg, 申请已提交); return result; }这里的状态字段建议用枚举值而不是中文比如0表示待审核、1表示已通过、2表示已驳回。中文状态在数据库里查询和统计时容易出问题尤其是考勤统计模块要做GROUP BY的时候。3.3 考勤查看与统计SQL 聚合查询怎么写学生端“我的考勤”和教师端“考勤统计”本质上是同一张attendance表的不同查询维度。学生端查自己的记录教师端查全班并按状态统计。核心 SQL 不复杂但要注意时间范围筛选和状态过滤。-- 学生端查看自己的考勤记录按时间倒序 SELECT a.id, a.check_time, a.location, a.photo_path, a.status, c.course_name FROM attendance a LEFT JOIN course c ON a.course_id c.id WHERE a.student_id #{studentId} ORDER BY a.check_time DESC; -- 教师端统计某班级某课程的签到情况 SELECT COUNT(*) AS total, SUM(CASE WHEN status 已审核 THEN 1 ELSE 0 END) AS approved, SUM(CASE WHEN status 待审核 THEN 1 ELSE 0 END) AS pending, SUM(CASE WHEN status 异常 THEN 1 ELSE 0 END) AS abnormal FROM attendance WHERE course_id #{courseId} AND check_time BETWEEN #{startTime} AND #{endTime};统计查询里用CASE WHEN做条件聚合比多次查询再拼装效率高。如果数据量不大这样写完全够用如果签到记录上千条建议在student_id、course_id、check_time上建联合索引。4. 教师端管理与审核从信息维护到签到人工审核4.1 学生与课程信息管理CRUD 接口的复用设计教师端的管理功能看起来多但底层都是 CRUD。学生信息管理、课程表管理、通知公告管理本质上都是增删改查。这套源码里BaseController和BaseDAO做了通用封装子类只需要继承并传入实体类型就能复用基础方法。// BaseController 通用 CRUD 示意 public abstract class BaseControllerT { Autowired protected BaseServiceT baseService; RequestMapping(/list) ResponseBody public ListT list() { return baseService.findAll(); } RequestMapping(/save) ResponseBody public MapString, Object save(RequestBody T entity) { MapString, Object result new HashMap(); baseService.insert(entity); result.put(code, 200); return result; } RequestMapping(/delete) ResponseBody public MapString, Object delete(Integer id) { baseService.deleteById(id); MapString, Object result new HashMap(); result.put(code, 200); return result; } }这种设计的好处是代码量少学生信息、课程、公告的 Controller 只需要继承BaseController并加上自己的业务方法。但要注意通用方法不包含业务校验比如删除课程时是否要检查有没有关联的签到记录这类逻辑必须在子类里重写。4.2 签到人工审核图片与位置的双重校验教师端签到审核是这套项目的特色功能。学生提交签到后记录进入待审核状态教师在后台看到列表点开详情能看到学生自拍照片和签到位置坐标。审核通过或标记异常状态更新。审核接口的核心逻辑是更新attendance表的status字段同时记录审核人和审核时间。这里有个容易忽略的点审核操作要做权限校验确保只有教师角色能调用否则学生端如果知道接口地址可以自己把状态改成“已审核”。// AttendanceController 审核方法 RequestMapping(/attendance/audit) ResponseBody public MapString, Object audit(RequestBody AuditRequest request) { MapString, Object result new HashMap(); // 权限校验从 session 或 token 中获取当前用户角色 User currentUser getCurrentUser(); if (!teacher.equals(currentUser.getRole())) { result.put(code, 403); result.put(msg, 无审核权限); return result; } Attendance record new Attendance(); record.setId(request.getAttendanceId()); record.setStatus(request.getStatus()); // 已审核 或 异常 record.setAuditTime(new Date()); record.setAuditBy(currentUser.getId()); attendanceService.update(record); result.put(code, 200); return result; }提示审核状态建议用数字枚举前端展示时再做映射。直接存中文“已审核”“异常”在数据库里不是不行但后续做统计查询时字符串匹配效率低而且容易因为空格或编码问题对不上。4.3 通知公告与课程表关联查询与前端渲染通知公告和课程表在小程序端是展示型功能后端提供列表接口前端渲染。课程表要注意的是一个学生可能属于多个课程查询时要按学生 ID 关联student_course中间表。通知公告则要注意发布时间排序和置顶逻辑。-- 查询某学生的课程表 SELECT c.id, c.course_name, c.teacher_name, c.classroom, c.week_day, c.start_section, c.end_section FROM course c INNER JOIN student_course sc ON c.id sc.course_id WHERE sc.student_id #{studentId} ORDER BY c.week_day, c.start_section; -- 查询通知公告置顶优先然后按时间倒序 SELECT id, title, content, create_time, is_top FROM notice ORDER BY is_top DESC, create_time DESC LIMIT 20;前端渲染课程表时常见做法是按week_day分组用表格或卡片布局展示。通知公告列表则直接遍历渲染点击进入详情页。这部分逻辑不复杂但要注意分页公告多了不能一次性全查出来。5. 避坑与排查这套源码跑不起来时先看这几条5.1 启动报错 ClassNotFoundException: com.mysql.jdbc.Driver现象Tomcat 启动时控制台报ClassNotFoundException指向 MySQL 驱动类。原因MySQL 驱动版本和驱动类名不匹配。MySQL 5.7 用com.mysql.jdbc.DriverMySQL 8.x 用com.mysql.cj.jdbc.Driver。另外驱动 jar 包没有放到WEB-INF/lib下也会报这个错。解决确认 MySQL 版本修改jdbc.properties里的jdbc.driver配置。如果是 Maven 项目检查pom.xml里mysql-connector-java的版本和 scope。非 Maven 项目手动把 jar 包放到WEB-INF/lib并 Add to Build Path。5.2 小程序端获取位置失败或返回 null现象调用uni.getLocation后没有回调或者返回的经纬度是 null。原因微信小程序从某个基础库版本开始获取位置需要在manifest.json里声明requiredPrivateInfos并且用户要授权位置权限。另外type参数必须设为gcj02用wgs84在微信里会返回不准确或失败。解决在manifest.json的mp-weixin节点下添加requiredPrivateInfos: [getLocation]并在app.json里配置permission字段说明位置用途。测试时用真机模拟器获取位置经常不准。5.3 图片上传后路径正确但显示 404现象签到自拍上传成功数据库里也有路径但教师端审核时图片加载不出来。原因上传的图片保存在服务器本地磁盘但 Tomcat 没有配置静态资源映射或者保存路径和访问路径不一致。解决在 SpringMVC 配置文件里加mvc:resources mapping/upload/** locationfile:/实际保存路径//确保 URL 访问路径和磁盘路径对应。另外上传目录要有写权限Linux 下注意chmod。5.4 中文乱码通知公告和学生姓名显示问号现象数据库里中文正常但小程序端和教师端显示乱码。原因数据库连接 URL 没加字符集参数或者 Tomcat 的server.xml里 Connector 没配URIEncoding。解决jdbc.url加上useUnicodetruecharacterEncodingutf8Tomcatserver.xml的 Connector 加URIEncodingUTF-8数据库和表的字符集统一用utf8mb4。5.5 签到审核后状态不更新或更新错行现象教师点审核通过提示成功但列表里状态没变或者改到了别的记录。原因前端传的attendanceId不对或者后端更新时WHERE条件写错。常见的是前端列表渲染时 ID 绑定错误或者后端用了updateByExample但条件没设对。解决先在浏览器 Network 里看审核请求的参数确认attendanceId是当前行的 ID。后端在update之前先select一次确认记录存在再更新。更新语句的WHERE条件建议用主键不要用其他字段。6. 二次开发与论文材料怎么把这份源码变成自己的东西这套资源除了源码还带了说明文档和论文材料LW。如果你是用来做毕业设计直接交这套代码风险很大因为查重和答辩都会问细节。我的习惯是先跑通再改三处最后把改的过程写成文档。第一处改的是签到审核逻辑。原版是纯人工审核你可以加一个自动判断如果签到位置和宿舍楼坐标距离超过 500 米自动标记为“位置异常”教师只需要审核异常记录。这样答辩时就有东西讲也体现了你对业务的理解。// 在签到提交时增加距离计算 public static double getDistance(double lat1, double lng1, double lat2, double lng2) { double radLat1 Math.toRadians(lat1); double radLat2 Math.toRadians(lat2); double a radLat1 - radLat2; double b Math.toRadians(lng1) - Math.toRadians(lng2); double s 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2), 2) Math.cos(radLat1) * Math.cos(radLat2) * Math.pow(Math.sin(b / 2), 2))); s s * 6378137; // 地球半径单位米 return Math.round(s * 10000) / 10000.0; }第二处改的是考勤统计的展示方式。原版是表格你可以加一个简单的图表用 ECharts 或者小程序端的图表组件把签到率、请假率、异常率画成饼图。教师端 dashboard 放一个图表答辩时视觉效果直接拉满。第三处改的是数据库索引。原版可能没建索引数据量一大查询就慢。在attendance表的student_id、course_id、check_time上建联合索引在leave_record表的student_id和status上建索引。改完用EXPLAIN对比一下查询类型从ALL变成ref或range这就是可以写进论文的优化点。-- 建索引前后用 EXPLAIN 对比 EXPLAIN SELECT * FROM attendance WHERE student_id 1 AND course_id 2; -- 建索引 ALTER TABLE attendance ADD INDEX idx_student_course (student_id, course_id); -- 再次 EXPLAIN观察 type 和 rows 的变化论文材料LW一般包含需求分析、系统设计、数据库设计、功能实现和测试。我的建议是不要直接复制把上面三处改动的过程、遇到的问题、怎么解决的写进去这就是你自己的东西。答辩时老师问“你做了什么”你能说出距离计算、图表展示、索引优化比背一遍 CRUD 流程强得多。从那以后我每次拿到一套源码都强制自己先跑通、再改三处、最后写一份改动记录。这套查寝打卡小程序的完整度不错前后端和数据库都能对上适合拿来练手或者做二次开发。希望帮到你。本文还有配套的精品资源点击获取