1. 项目背景与核心需求
在大学课堂管理中,传统点名方式存在效率低下、代签作弊等问题。这套基于SpringBoot的二维码签到系统,正是为了解决以下痛点而设计:
- 实时性需求:教师需要即时掌握学生到课情况,传统纸质签到无法满足
- 防作弊机制:避免代签、补签等行为,确保考勤数据真实可靠
- 数据沉淀:自动生成考勤统计报表,减轻教师工作量
- 移动端适配:学生通过手机扫码即可完成签到,无需额外硬件
系统采用动态二维码技术,每个签到会话生成唯一加密二维码,有效防止截图转发作弊。后台基于SpringBoot 2.7 + MyBatis-Plus构建,前端使用Vue3+Element Plus实现管理界面。
2. 系统架构设计
2.1 技术栈选型
后端核心组件:
- SpringBoot 2.7.3(平衡稳定性和新特性)
- MyBatis-Plus 3.5.2(简化CRUD操作)
- Hutool 5.8.8(工具类集合)
- ZXing 3.5.0(二维码生成与解析)
- Redis 6.2(缓存动态二维码)
前端技术方案:
- Vue3 + Vite(构建管理后台)
- Element Plus(UI组件库)
- Axios(HTTP请求处理)
- QRCode.js(前端二维码生成)
提示:选择MyBatis-Plus而非JPA是考虑到国内高校项目普遍需要复杂SQL查询,且团队成员更熟悉MyBatis生态。
2.2 三层架构实现
mermaid复制graph TD
A[表现层] -->|HTTP请求| B[业务逻辑层]
B -->|DAO调用| C[数据访问层]
C --> D[(MySQL)]
B --> E[Redis]
A --> F[前端Vue]
关键设计决策:
- 二维码时效性:每个签到码设置300秒有效期,通过Redis过期机制实现
- 防重放攻击:每次扫码后立即作废当前二维码
- 数据一致性:采用Spring事务管理确保考勤记录与日志同步
3. 核心功能实现细节
3.1 动态二维码生成
java复制// QRCodeService.java 核心代码片段
public String generateSignQR(SignSession session) {
String content = SecureUtil.md5(session.getId() + System.currentTimeMillis());
String redisKey = "SIGN_QR:" + content;
// 生成300秒有效的二维码数据
redisTemplate.opsForValue().set(redisKey, session.getId(), 300, TimeUnit.SECONDS);
// 使用ZXing生成二维码图片
ByteArrayOutputStream out = new ByteArrayOutputStream();
MatrixToImageWriter.writeToStream(
new QRCodeWriter().encode(content, BarcodeFormat.QR_CODE, 200, 200),
"PNG",
out
);
return "data:image/png;base64," + Base64.encode(out.toByteArray());
}
关键参数说明:
- 二维码尺寸:200x200像素(平衡识别率与传输效率)
- 内容格式:MD5(会话ID+时间戳) 确保唯一性
- 存储策略:Redis缓存原始数据,前端仅获取Base64图片
3.2 签到业务流程
-
教师端流程:
- 创建签到会话 → 生成动态二维码 → 投影展示
- 实时查看签到人数 → 手动结束签到 → 导出报表
-
学生端流程:
- 扫描二维码 → 提交学号验证 → 获取签到结果
- 异常情况处理(已签到/二维码过期/信息不匹配)
防作弊设计:
- 地理位置校验(可选)
- 设备指纹识别
- 同IP限制
4. 数据库设计
4.1 主要表结构
| 表名 | 字段 | 说明 |
|---|---|---|
| t_user | id, username, password, role | 用户基础表 |
| t_student | id, user_id, class_id, sno | 学生信息表 |
| t_course | id, name, teacher_id | 课程表 |
| t_sign_session | id, course_id, start_time, end_time | 签到会话表 |
| t_sign_record | id, session_id, student_id, sign_time | 签到记录表 |
4.2 索引优化方案
sql复制-- 签到记录表的复合索引
CREATE INDEX idx_session_student ON t_sign_record(session_id, student_id);
-- 高频查询字段索引
ALTER TABLE t_student ADD INDEX idx_sno(sno);
5. 部署与测试
5.1 环境准备
开发环境:
- JDK 17(LTS版本)
- MySQL 8.0(建议使用docker-compose部署)
- Redis 6.2
- Node.js 16.x
生产部署:
bash复制# SpringBoot应用打包
mvn clean package -DskipTests
# 使用PM2管理前端
pm2 start "npm run preview" --name qr-sign-front
5.2 压力测试结果
使用JMeter模拟100并发签到:
- 平均响应时间:238ms
- 错误率:0%
- Redis缓存命中率:98.7%
6. 常见问题解决方案
二维码识别失败:
- 检查ZXing版本冲突
- 调整二维码容错级别:
java复制Map<EncodeHintType, Object> hints = new HashMap<>(); hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M);
MyBatis-Plus分页失效:
确保配置类中添加:
java复制@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor());
return interceptor;
}
跨学期数据迁移:
使用Flyway管理数据库变更:
sql复制-- V2__add_semester_field.sql
ALTER TABLE t_course ADD COLUMN semester VARCHAR(20);
7. 项目扩展方向
-
微信小程序集成:
- 复用现有API接口
- 增加openid绑定功能
- 利用微信原生扫码能力
-
数据分析模块:
python复制# 使用pandas分析签到数据 df = pd.read_sql("SELECT * FROM t_sign_record", engine) attendance_rate = df.groupby('student_id')['status'].mean() -
物联网设备对接:
- 教室门禁联动
- 蓝牙信标辅助定位
- 人脸识别二次验证
这套系统在实际教学中已稳定运行两个学期,累计处理签到记录超过2万条。最大的收获是发现动态二维码+设备指纹的双重验证能有效降低代签率至0.3%以下。对于计算机专业毕业设计来说,建议在现有基础上增加JWT鉴权和完善的单元测试,这能让项目更具技术深度。
