ARTICLE DETAIL

资讯详情

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

Java+微信小程序学习打卡系统源码实战:环境搭建、登录对接与避坑指南

Java+微信小程序学习打卡系统源码实战:环境搭建、登录对接与避坑指南 简介这是一套面向Java与微信小程序方向学生及开发者的日常学习打卡系统完整项目包适合用作毕业设计、课程设计或全栈入门实践。项目以微信小程序为前端结合Java后端与云开发能力实现用户注册登录、学习计划创建与加入、每日打卡记录、进度追踪及统计分析等功能帮助使用者理解前后端协同与Serverless架构的落地方式。压缩包共71个文件约840KB包含json配置、js逻辑、wxml与wxss页面样式、png界面截图以及docx、doc、txt、md说明文档和mp4演示视频覆盖源码、需求分析、数据库设计截图、开发环境清单与项目问题说明。目前已有509人学习下载。通过研读源码可掌握小程序页面路由、数据绑定与网络请求以及Spring Boot、MyBatis与MySQL的整合技巧配合文档与录屏能系统复现整个项目并积累排错经验。1. 从一份 Java 学习打卡小程序源码说起它到底能解决什么问题打开招聘网站Java 岗位的简历里十个有八个写着「熟悉微信小程序」但真正能拿出一个完整可运行项目的人并不多。这份「基于微信小程序的日常学习打卡系统」源码包恰好卡在一个很实用的位置上后端用 Java 写业务逻辑前端用微信小程序做用户入口中间靠 HTTP 接口打通功能覆盖用户登录、打卡记录、学习时长统计、排行榜这几个学习类产品的核心闭环。它不是一个玩具 Demo而是一套能直接跑起来、能改、能当课程设计或毕设底座的东西。适合谁看第一类是在做 Java 课程设计、需要交一个「有前端有后端」完整项目的学生第二类是想转小程序开发、但缺一个真实业务场景练手的后端工程师第三类是接私活时需要快速搭一个打卡类产品原型的独立开发者。这篇笔记不吹这套源码多完美而是把它拆开讲清楚环境怎么搭、登录怎么接、打卡逻辑写在哪、统计怎么做、哪些地方一跑就翻车。看完你应该能自己判断这套东西值不值得拿来改造成自己的项目。2. 环境搭建与工程结构把 Java 后端和微信小程序跑起来2.1 先看清这套源码的技术栈和目录长什么样拿到一个.zip源码包最忌讳的就是直接双击导入 IDE 然后报一堆红。先解压用文件管理器把目录结构扫一遍心里有个数。这类「Java 微信小程序」的打卡系统常见结构是前后端分两个目录放一个后端工程目录通常叫server、backend或直接是 Maven 工程根目录一个小程序目录通常叫miniprogram、wxapp或client。后端里能看到pom.xml或build.gradle小程序目录里能看到app.json、app.js、pages文件夹。判断技术栈最直接的办法是看依赖文件。打开pom.xml如果看到spring-boot-starter-web、mybatis-spring-boot-starter、mysql-connector-java这几个基本可以确定是 Spring Boot MyBatis MySQL 的经典组合。这套组合在国内 Java 课程设计和中小型项目里出现频率极高好处是资料多、出问题好搜坏处是版本兼容坑也多。小程序端看app.json里的pages数组能直接读出这个系统有几个页面打卡系统一般会有首页、打卡页、记录页、个人中心这几个。提示解压后先别急着改代码把目录结构和依赖文件看明白比直接跑起来更重要。很多「跑不起来」的问题根源是根本没搞清楚项目用了什么。2.2 后端启动数据库、配置、依赖三步走后端能不能起来九成取决于数据库和配置文件对不对。第一步是建库建表。源码包里通常会带一个.sql文件名字可能是db.sql、init.sql或learning_checkin.sql。用命令行导入比用图形工具更可控# 登录 MySQL创建数据库字符集用 utf8mb4否则中文和 emoji 会乱码 mysql -u root -p -e CREATE DATABASE checkin_db DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; # 导入源码包里的建表脚本注意替换成实际文件名 mysql -u root -p checkin_db db.sql # 确认表建好了打卡系统一般至少有 user、checkin_record、study_log 这几张表 mysql -u root -p checkin_db -e SHOW TABLES;建库时字符集一定要用utf8mb4这是血泪经验。用默认的utf8存用户昵称里的 emoji 会直接报错或者存成问号而微信小程序拿到的用户昵称里带 emoji 太常见了。导入完成后SHOW TABLES应该能看到用户表、打卡记录表这些。第二步改配置文件。Spring Boot 的配置一般在src/main/resources/application.yml或application.properties。要改的核心就三处数据库连接、端口、以及如果有的话 Redis 配置。server: port: 8080 # 后端服务端口小程序请求要对应这个 spring: datasource: url: jdbc:mysql://localhost:3306/checkin_db?useUnicodetruecharacterEncodingutf8mb4serverTimezoneAsia/Shanghai username: root password: 你的密码 driver-class-name: com.mysql.cj.jdbc.DriverserverTimezoneAsia/Shanghai这个参数不加MySQL 8 以上版本启动时经常报时区错误这是最常见的翻车点之一。characterEncodingutf8mb4要和建库时的字符集对上。第三步启动。用 Maven 的话在工程根目录执行# 先清理再打包跳过测试避免测试用例连不上库导致打包失败 mvn clean package -DskipTests # 直接运行打出来的 jar或者用 IDE 跑主启动类 java -jar target/xxx-0.0.1-SNAPSHOT.jar看到控制台打印出 Tomcat started on port 8080 之类的日志后端就算起来了。如果卡在启动阶段先看报错关键词Access denied是密码错Unknown database是库名错Table doesnt exist是没导入 SQLCommunications link failure是 MySQL 没启动或端口不对。2.3 小程序端改请求地址、配 AppID、真机预览小程序端跑起来比后端简单但有两个必改项。第一是请求的后端地址。小程序里所有wx.request调用的url前缀通常集中定义在一个配置文件里比如config.js或utils/request.js。找到它把地址改成你后端实际跑的地址。// utils/config.js 或类似文件把 baseUrl 改成后端地址 const config { // 本地开发用 localhost 在真机上不通真机要用局域网 IP baseUrl: http://192.168.1.100:8080, // 接口版本前缀和后端 Controller 的 RequestMapping 对应 apiPrefix: /api } module.exports config这里有个新手必踩的坑在微信开发者工具里用localhost能通但一扫码到真机就请求失败。原因是真机上的localhost指向手机自己不是你的电脑。真机调试必须把地址换成电脑的局域网 IP并且手机和电脑连同一个 WiFi。第二是 AppID。app.json或项目配置里如果填的是别人的 AppID你没法预览和上传。在微信开发者工具里点「详情」把 AppID 改成自己的测试号或者正式 AppID。没有 AppID 的话用「测试号」也能跑通大部分功能只是部分接口受限。改完这两处点开发者工具的「编译」模拟器里应该能看到登录页或首页。如果页面白屏先看控制台报错多半是baseUrl写错或者后端没起来。3. 登录与打卡核心逻辑微信登录怎么接、打卡记录怎么写3.1 微信小程序登录获取手机号code 换 openid 的完整链路微信小程序的登录不是传统的账号密码而是一套code换openid的机制。用户点登录小程序调wx.login拿到一个临时code把这个code发给后端后端拿code加上小程序的AppID和AppSecret去请求微信服务器换回openid和session_key。openid就是用户在这个小程序里的唯一标识拿它去数据库里查或建用户。小程序端发起登录// pages/login/login.js wx.login({ success: (res) { if (res.code) { // 把 code 发给自己的后端由后端去换 openid wx.request({ url: config.baseUrl /api/user/login, method: POST, data: { code: res.code }, success: (resp) { // 后端返回自定义登录态 token存起来后续请求带上 wx.setStorageSync(token, resp.data.data.token) } }) } } })后端处理code换openid的逻辑核心是拼一个请求微信接口的 URL。这里AppID和AppSecret必须放在后端绝不能写在小程序里否则等于把密钥公开了。// UserController.java 里处理登录的核心逻辑 PostMapping(/login) public Result login(RequestBody LoginDTO dto) { // 用 code 去微信服务器换 openidappid 和 secret 从配置文件读 String url https://api.weixin.qq.com/sns/jscode2session ?appid appId secret appSecret js_code dto.getCode() grant_typeauthorization_code; // 用 RestTemplate 或 HttpClient 发请求解析返回的 openid String resp restTemplate.getForObject(url, String.class); JSONObject json JSON.parseObject(resp); String openid json.getString(openid); // 用 openid 查用户没有就新建然后生成自己的 token 返回 User user userService.findOrCreateByOpenid(openid); String token jwtUtil.generateToken(user.getId()); return Result.success(new LoginVO(token, user)); }参数说明appid和appSecret从小程序后台「开发管理」里拿js_code就是前端传来的codegrant_type固定写authorization_code。返回的 JSON 里如果带errcode说明换失败了常见的是40029code 无效一般是 code 被用过或过期和40163code 已被使用。code只能用一次所以前端不要重复提交同一个 code。至于「微信小程序登录获取手机号」那是另一套流程需要用户主动点授权按钮前端拿到加密的encryptedData和iv后端用session_key解密。打卡系统里如果只是记录学习用openid就够了不必强求手机号强求反而增加用户流失。3.2 打卡记录写入防重复打卡和时区处理打卡功能看着简单写起来坑不少。核心就一条一个用户一天只能打一次卡。实现方式有两种一种是在数据库层加唯一索引一种是在业务层先查再插。稳妥的做法是两个都上。数据库层加唯一索引让数据库帮你兜底-- 给打卡记录表加联合唯一索引user_id checkin_date 组合唯一 ALTER TABLE checkin_record ADD UNIQUE KEY uk_user_date (user_id, checkin_date);业务层先查后插给用户友好提示// CheckinService.java public Result doCheckin(Long userId) { // 用当天日期作为打卡日期注意时区 LocalDate today LocalDate.now(ZoneId.of(Asia/Shanghai)); // 先查今天有没有打过 CheckinRecord exist checkinMapper.selectByUserAndDate(userId, today); if (exist ! null) { return Result.fail(今天已经打过卡啦); } CheckinRecord record new CheckinRecord(); record.setUserId(userId); record.setCheckinDate(today); record.setCreateTime(new Date()); try { checkinMapper.insert(record); } catch (DuplicateKeyException e) { // 并发下唯一索引兜底捕获重复插入异常 return Result.fail(今天已经打过卡啦); } return Result.success(打卡成功); }时区是这里最容易被忽略的点。服务器如果是 UTC 时间LocalDate.now()拿到的日期可能和用户所在时区差一天导致用户晚上十一点打卡被算成第二天。所以显式指定Asia/Shanghai时区别用默认的。DuplicateKeyException这个捕获也不能省两个请求同时进来时先查后插之间有时间窗口唯一索引是最后一道防线。3.3 学习时长统计与排行榜一条 SQL 搞定还是分步算打卡系统光有打卡不够用户想看自己这周学了多久、在排行榜上排第几。统计逻辑有两种实现思路一种是用 SQL 聚合直接算一种是查出来在 Java 里算。数据量小的时候两种都行数据量大了 SQL 聚合明显更优因为不用把大量记录拉到内存。按周统计学习时长用 SQL 的日期函数分组-- 统计某用户本周每天的学习时长checkin_date 是打卡日期duration 是分钟数 SELECT checkin_date, SUM(duration) AS total_minutes FROM study_log WHERE user_id #{userId} AND checkin_date #{weekStart} AND checkin_date #{weekEnd} GROUP BY checkin_date ORDER BY checkin_date;排行榜则是按总时长倒序取前 N 名-- 本周学习时长排行榜取前 20 名 SELECT u.nickname, u.avatar, SUM(s.duration) AS total_minutes FROM study_log s JOIN user u ON s.user_id u.id WHERE s.checkin_date #{weekStart} GROUP BY s.user_id ORDER BY total_minutes DESC LIMIT 20;参数说明weekStart和weekEnd是本周的起止日期在 Java 里用LocalDate.now().with(DayOfWeek.MONDAY)算出来传进去。LIMIT 20控制返回条数排行榜一般不需要全量。如果排行榜访问频繁每次都查库压力大可以加一层 Redis 缓存按周为 key 缓存排行榜结果过期时间设成一周。注意排行榜的JOIN查询在用户量上万后会变慢study_log表的user_id和checkin_date上要建索引否则全表扫描。4. 避坑与排查这套打卡系统最容易翻车的五个地方4.1 真机请求失败开发者工具却正常现象微信开发者工具里所有接口都通一扫码到真机就全部请求失败控制台报request:fail。原因开发者工具默认关闭了域名校验而真机默认开启。同时localhost在真机上指向手机自己不是你的开发机。解决开发阶段在微信开发者工具「详情 - 本地设置」里勾选「不校验合法域名」真机调试时把baseUrl换成电脑的局域网 IP用ipconfig或ifconfig查确保手机和电脑同一 WiFi。上线前必须把后端域名配到小程序后台的「服务器域名」白名单里且必须是 HTTPS。4.2 中文和 emoji 存进数据库变问号现象用户昵称里的 emoji 或生僻字存进 MySQL 后变成???或乱码。原因建库或建表时字符集用了utf8而不是utf8mb4。MySQL 的utf8最多存 3 字节emoji 是 4 字节存不下。解决建库时指定DEFAULT CHARACTER SET utf8mb4连接 URL 里加characterEncodingutf8mb4已经建好的表用ALTER TABLE 表名 CONVERT TO CHARACTER SET utf8mb4;转换。三处都要改只改一处没用。4.3 打卡日期差一天现象用户明明今天打的卡记录里显示的是昨天或明天。原因服务器时区是 UTCnew Date()或LocalDate.now()拿到的是 UTC 日期和北京时间差 8 小时。解决JVM 启动参数加-Duser.timezoneAsia/Shanghai或者在代码里显式用ZoneId.of(Asia/Shanghai)。数据库连接 URL 里的serverTimezone也要设对。这是最隐蔽的坑因为白天测试看不出来晚上八点后测试才会暴露。4.4 并发打卡插入重复记录现象用户快速连点打卡按钮数据库里出现两条同一天的记录。原因先查后插之间有时间窗口两个请求都查到「没打过」然后都执行了插入。解决数据库层加user_id checkin_date的联合唯一索引业务层捕获DuplicateKeyException。前端也要做按钮防抖点击后置灰几秒。三层防护缺一不可只靠前端防抖挡不住直接调接口的情况。4.5 小程序页面列表加载更多不触发现象打卡记录列表往下滑加载更多的逻辑不执行或者重复加载同一页数据。原因onReachBottom没在页面配置里生效或者分页参数page没正确自增导致每次请求都是第一页。解决确认页面.json里没有禁用onReachBottom在onReachBottom回调里维护一个page变量每次加载成功后page同时用一个loading标志位防止重复触发。请求返回空数组时把hasMore置为false停止继续加载。5. 二次开发进阶把打卡系统改成你自己的项目5.1 从打卡到学习社区三个可落地的扩展方向这套源码的骨架是「用户 打卡 统计」往哪个方向改取决于你的目标。如果是为了毕设加分加一个「学习计划」模块最实用用户可以设定每周目标时长系统根据打卡记录算完成度用进度条展示。数据库加一张study_plan表字段包括user_id、target_minutes、week_start统计逻辑复用现有的时长聚合 SQL。如果是为了做产品原型加「打卡提醒」能显著提升留存。微信小程序的订阅消息可以做到这一点用户打卡时请求订阅授权后端在固定时间通过微信的订阅消息接口推送提醒。核心是拿到用户的openid和订阅模板 ID调subscribeMessage.send接口。注意订阅消息是一次授权一次推送不能无限推。如果是为了练技术把统计部分从实时查库改成定时任务预计算。用 Spring 的Scheduled每天凌晨跑一次把每个用户的历史统计结果算好存到一张汇总表里前端查询直接读汇总表。这样排行榜和统计页的响应速度会快一个量级代价是数据有最多一天的延迟。5.2 验证改造是否成功三个必测场景改完代码别急着交付这三个场景必须测。第一新用户首次登录到首次打卡的完整链路确认openid正确创建用户、打卡记录正确关联。第二同一用户连续两天打卡确认日期不重复、统计数字正确累加。第三模拟并发打卡用两个请求同时打确认数据库里只有一条记录。这三个场景覆盖了登录、打卡、统计三条主链路过了基本就没大问题。测试并发打卡可以用简单的 shell 脚本# 同时发 5 个打卡请求验证唯一索引是否生效 for i in $(seq 1 5); do curl -X POST http://localhost:8080/api/checkin \ -H token: 你的测试token done wait # 然后查数据库确认当天只有一条记录 mysql -u root -p checkin_db -e SELECT COUNT(*) FROM checkin_record WHERE user_id1 AND checkin_dateCURDATE();返回的COUNT应该是 1。如果是 5说明唯一索引没生效或者没建赶紧回去补。5.3 我踩过的那些坑和现在的习惯做这类打卡系统我最大的教训是「别信默认配置」。MySQL 默认字符集、JVM 默认时区、小程序默认域名校验这三个默认值每一个都能让你调试半天。现在的习惯是拿到任何源码先看字符集、时区、端口这三处配置改完再跑。第二个习惯是数据库约束永远比业务代码可靠能在数据库层加的约束就别只写在 Java 里代码会改索引不会自己消失。第三个习惯是打卡类功能一定要在晚上八点后测一次时区问题白天根本看不出来。这套源码值不值得投入如果你需要一个能跑通的 Java 小程序全栈项目当底座它省了你搭架子的一两周时间值得。但别指望它开箱即用环境配置、登录对接、时区处理这几处该改的还得改。把它当成一个起点而不是终点。希望帮到你。本文还有配套的精品资源点击获取
返回列表