☰
SSM+MySQL查寝打卡小程序源码拆解:从环境搭建到二次开发
2026/10/22 3:00:19 网站建设 项目流程

简介:这是一套面向高校计算机相关专业学生的查寝打卡微信小程序毕业设计源码,采用Java+SSM框架开发服务端,小程序端基于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 后端环境选型与版本对齐

这套源码的技术栈是 SSM(Spring + SpringMVC + MyBatis),服务器指定 Tomcat 7,JDK 版本 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 里要带上useUnicode=true&characterEncoding=utf8,否则中文通知公告会变成问号。

# jdbc.properties 关键配置 jdbc.driver=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/dorm_check?useUnicode=true&characterEncoding=utf8&useSSL=false jdbc.username=root jdbc.password=你的密码

提示:MySQL 5.7 的驱动类名是com.mysql.jdbc.Driver,如果你用的是 MySQL 8.x,驱动类名要改成com.mysql.cj.jdbc.Driver,URL 也要加时区参数。这套源码指定的是 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> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>4.3.xx</version> <!-- 版本以源码为准 --> </dependency> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.4.xx</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.xx</version> </dependency>

Tomcat 配置时,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 Map<String, Object> applyLeave(@RequestBody LeaveRecord record) { Map<String, 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 BaseController<T> { @Autowired protected BaseService<T> baseService; @RequestMapping("/list") @ResponseBody public List<T> list() { return baseService.findAll(); } @RequestMapping("/save") @ResponseBody public Map<String, Object> save(@RequestBody T entity) { Map<String, Object> result = new HashMap<>(); baseService.insert(entity); result.put("code", 200); return result; } @RequestMapping("/delete") @ResponseBody public Map<String, Object> delete(Integer id) { baseService.deleteById(id); Map<String, Object> result = new HashMap<>(); result.put("code", 200); return result; } }

这种设计的好处是代码量少,学生信息、课程、公告的 Controller 只需要继承BaseController并加上自己的业务方法。但要注意:通用方法不包含业务校验,比如删除课程时是否要检查有没有关联的签到记录,这类逻辑必须在子类里重写。

4.2 签到人工审核:图片与位置的双重校验

教师端签到审核是这套项目的特色功能。学生提交签到后,记录进入待审核状态,教师在后台看到列表,点开详情能看到学生自拍照片和签到位置坐标。审核通过或标记异常,状态更新。

审核接口的核心逻辑是更新attendance表的status字段,同时记录审核人和审核时间。这里有个容易忽略的点:审核操作要做权限校验,确保只有教师角色能调用,否则学生端如果知道接口地址,可以自己把状态改成“已审核”。

// AttendanceController 审核方法 @RequestMapping("/attendance/audit") @ResponseBody public Map<String, Object> audit(@RequestBody AuditRequest request) { Map<String, 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.Driver,MySQL 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/**" location="file:/实际保存路径/"/>,确保 URL 访问路径和磁盘路径对应。另外,上传目录要有写权限,Linux 下注意chmod。

5.4 中文乱码:通知公告和学生姓名显示问号

现象:数据库里中文正常,但小程序端和教师端显示乱码。

原因:数据库连接 URL 没加字符集参数,或者 Tomcat 的server.xml里 Connector 没配URIEncoding。

解决:jdbc.url加上useUnicode=true&characterEncoding=utf8;Tomcatserver.xml的 Connector 加URIEncoding="UTF-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 流程强得多。

从那以后我每次拿到一套源码,都强制自己先跑通、再改三处、最后写一份改动记录。这套查寝打卡小程序的完整度不错,前后端和数据库都能对上,适合拿来练手或者做二次开发。希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询