ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

微信小程序+Spring Boot社团活动管理毕设实战全解析

微信小程序+Spring Boot社团活动管理毕设实战全解析 1. 项目概述与设计思路拆解1.1 毕设为什么选这个题目每年毕设季微信小程序类的题目都是大热门。我当初选这个题目原因比较实际一是微信小程序生态成熟前端开发成本低不用考虑Android和iOS两套适配一个代码库两边跑二是“社团活动管理”这个业务场景足够典型用户角色分明、流程清晰该有的增删改查、登录鉴权、状态流转全都有非常适合用来展示完整的技术栈三是青年志愿者协会这种组织在高校里普遍存在答辩时评审老师容易理解业务逻辑不太会出现“你这个项目解决的是什么问题”这种尴尬场面。当然还有一个隐藏原因——这类项目网上开源版本不少但大多要么只有前端没有后端、要么代码老得跑不起来。真正拿回来能直接当毕设交付的很少。所以我决定自己完整做一套微信小程序端 Java后端接口 MySQL数据库再配一个管理后台Web版把从前端到后端再到部署的整条链路走通。这套系统最终实现的核心功能有微信授权登录、志愿者注册与身份认证、社团活动发布、活动报名与取消、签到打卡、志愿时长自动累计、公告通知、活动分类检索、后台数据统计。如果你的毕设也需要“亮点模块”时间统计和导出报表是性价比很高的加分项。1.2 技术选型的底层逻辑技术栈选型这件事很多人直接照着网上的“毕设套餐”抄但最好还是理解一下为什么选它。前端微信小程序原生框架。没有用uni-app也没有用Taro。原因很简单毕设周期有限原生框架虽然写起来啰嗦但调试最直接文档最全踩坑的时候搜到的解决方案也最多。用跨端框架反而会引入一层“黑盒”一旦出问题排查成本很高。后端Spring Boot 2.x MyBatis-Plus。Spring Boot在Java生态里已经是事实标准学过的同学上手很快。MyBatis-Plus有很实用的代码生成器可以自动生成实体类、Mapper接口、Service层能省下大量重复劳动。数据库用MySQL——这个没什么好争论的教科书默认选型资料最多。鉴权方案微信登录code2session 自定义Token。小程序端通过wx.login()获取临时code后端拿着code调微信接口换openid和session_key然后签发一个自定义Token返回给小程序。后续请求带上Token后端拦截器统一校验。这套方案的效果是用户无需注册密码一键登录体验好后端不直接暴露openid相对安全。代价是额外写一层拦截器和Token下发逻辑但对毕设来说这是展示你“理解业务闭环”的好素材。1.3 核心需求解析与角色权限模型志愿者协会的社团活动管理表面上看起来就是“活动报名”四个字但实际上牵扯到三类角色每个角色的需求完全不同。我接触过不少同学把这块做简单了——只做一个“用户能发布活动、能报名”答辩时被问一句“那谁来审核报名人数超了怎么办”就答不上来。所以我在设计阶段就把角色权限单独拎出来理了一遍。普通志愿者协会成员浏览活动、报名/取消活动、查看活动详情、签到打卡、查看自己的累计志愿时长、接收公告通知。这是使用频率最高的角色。管理员协会部长/会长在普通志愿者权限基础上拥有活动发布权限待审核、活动审核权限、成员管理权限审核入会申请、时长手动调整权限、公告发布权限。超级管理员指导老师/系统维护者拥有全部权限包括管理员账号分配、活动数据导出、系统参数配置。在实现上我用一个整型字段role区分0代表普通成员1代表管理员2代表系统管理员。接口层通过拦截器校验角色比如RequireRole(1)这种注解把权限逻辑和业务逻辑分开。数据库表结构上用户表member、活动表activity、报名表registration、公告表notice、社团表association是最核心的五张表。活动审核状态我用status字段表示0草稿、1待审核、2审核通过且未开始、3已结束、4已取消。报名状态用0报名1取消2签到。这种状态机设计在毕设文档里也很有话可讲。2. 小程序端功能拆解与页面设计2.1 页面结构与分包加载策略小程序端我拆成了7个主页面首页活动流、活动详情页、活动发布页、我的报名页、个人中心页、公告页、登录页。底部TabBar只放了四个首页、活动分类聚合页、公告、我的。首页默认展示“即将开始”的活动卡片列表卡片上显示活动名称、时间地点、剩余名额。下拉刷新、触底加载更多这两个交互是必须做的——不用封装太复杂的组件库微信自带的onPullDownRefresh和onReachBottom生命周期函数就能搞定。分包加载这件事毕设项目虽然用不上但是写文档的时候可以提一下。微信小程序有2MB主包限制我把“活动发布页”和“公告详情页”放到了分包里主包体积控制在了1.8MB左右。答辩时这个细节能体现你对小程序平台规范的了解。页面路由逻辑要注意一点活动详情页从首页和“我的报名页”都可能进入返回逻辑不一样。我用了wx.navigateTo传参在详情页设置了一个from参数返回时根据参数决定是wx.navigateBack还是wx.switchTab。这个细节不处理好的话用户在报名页看到一半想返回结果直接退出了小程序很影响体验。2.2 登录鉴权流程与静默登录微信小程序登录需要理解一次典型的登录链路。wx.login()会返回一个临时的code有效期5分钟且只能用一次。拿到code之后小程序端要调自己后端的登录接口后端再拿code去微信的code2session接口换取openid和session_key。这里有个关键点session_key绝对不能下发到前端更不能存到自己的数据库里它是微信用来解密用户手机号、获取用户信息的密钥。后端换取openid之后自己生成一个Token我用的是UUID也可以用JWT把openid和Token的映射关系存到Redis或MySQL中。如果是开发阶段没有AppSecret或者后端没部署到线上调试登录会很麻烦。我的做法是在后端加了一个“开发模式”开关——如果配置项里devLogintrue后端直接放行用测试账号的openid代替微信登录。这个开关在答辩的时候也可以提一下说这是为了环境隔离。2.3 活动发布与报名模块的设计细节活动发布页是管理员用的核心功能。字段包括活动名称、活动封面、活动分类环保、支教、敬老、赛事服务等、开始时间、结束时间、报名截止时间、活动地点、最大人数限制、活动详情富文本。富文本编辑器是微信原生组件editor但说实话它输出的HTML格式有点奇怪部分标签后端解析容易出问题。我的处理是在提交时用wx.getFileSystemManager读内容做一次清洗只保留p、img、section标签其他全部剥掉。如果你不想折腾富文本降级方案是用textarea做纯文本详情加上几张配图毕设完全够用。报名模块要注意并发问题。同一个活动剩最后一个名额时两个人同时点击报名如果代码先查COUNT(*)再判断是否小于限制再插入极端情况下会出现超员。我在activity表上加了version字段做乐观锁更新剩余名额时用UPDATE activity SET remain_count remain_count - 1 WHERE activity_id ? AND remain_count 0影响行数为0说明名额已被抢完。签到功能用的是二维码方案管理员在活动当天生成一个动态二维码志愿者扫描后点击“签到”后端记录签到时间志愿时长按“活动实际结束时间 - 签到时间”自动计算并累加到用户表。如果没有签到场景也可以用核销码但二维码方案在答辩时更容易讲出亮点。3. 后端接口设计与数据库建模3.1 表结构设计与关键字段说明数据库是这套系统的根基表设计得好不好直接关系后面写代码的效率。我最终落地的表和字段如下表名核心字段说明memberid, openid, nickname, avatar, real_name, student_no, college, phone, role, total_hours, status用户表role区分角色total_hours累计志愿时长activityid, title, cover, category, content, start_time, end_time, signup_deadline, location, max_count, remain_count, status, create_by, version活动表status控制审核流registrationid, activity_id, member_id, status, create_time, signin_time报名表同一个会员对同一活动只能有一条记录noticeid, title, content, create_by, create_time, top_flag公告表top_flag置顶associationid, name, description, avatar, members_count社团表用于展示和成员统计两个索引要建registration(activity_id, member_id)联合唯一索引防止一个人重复报名同一活动activity(status, start_time)联合索引加速首页活动列表查询。这两个索引在数据量上来之后区别很大毕设文档里也值得写一笔。数据库字符集统一用utf8mb4记住千万别用utf8否则用户昵称里的emoji会存不进去后果是登录的时候数据库直接报错前端一直在“加载中”转圈。3.2 核心接口列表与控制层实现后端接口风格是RESTful统一返回结构{ code, message, data }。我列一下核心接口后续自己扩展功能时可参照方法路径功能权限POST/api/auth/login微信登录传code返回token和用户信息无需登录GET/api/activities活动列表支持分页、分类筛选、关键字搜索登录GET/api/activities/{id}活动详情登录POST/api/activities发布活动管理员PUT/api/activities/{id}/audit审核活动管理员POST/api/registrations报名活动传activityId登录DELETE/api/registrations/{id}取消报名本人POST/api/registrations/signin签到传activityId qrCode本人GET/api/registrations/my我的报名列表登录GET/api/stats/overview活动统计与时长排行管理员GET/api/notices公告列表登录登录接口的核心代码可用下面这个结构伪代码风格PostMapping(/api/auth/login) public Result login(RequestBody LoginRequest req) { // 1. 用appId appSecret code 换 openid String openid wxService.code2Session(req.getCode()); // 2. 查数据库没有就自动注册 Member member memberMapper.selectByOpenid(openid); if (member null) { member new Member(); member.setOpenid(openid); member.setNickname(微信用户 openid.substring(openid.length() - 6)); member.setRole(0); memberMapper.insert(member); } // 3. 生成token存redis设置7天过期 String token UUID.randomUUID().toString().replace(-, ); redisTemplate.opsForValue().set(token: token, member.getId().toString(), 7, TimeUnit.DAYS); // 4. 返回数据 return Result.success(new LoginVO(token, member)); }Controller层尽量只做参数接收和结果封装业务逻辑下沉到Service层。项目里的ActivityServiceImpl是最长的一个类光报名活动这一个方法就处理了“校验登录角色、校验活动状态是否可报名、校验是否已过截止时间、校验是否重复报名、校验名额是否已满”五种异常情况。每抛一个业务异常前端就弹一个对应的toast提示——这些小细节拼接起来就是产品的完成度。3.3 后端部署与本地联调建议后端联调阶段我踩过最大的坑是跨域问题。如果你本地跑后端比如8080端口小程序端请求http://localhost:8080/api/xxx是会报错的因为微信小程序要求请求地址必须是HTTPS。但在微信开发者工具里可以在“详情 → 本地设置”中勾选“不校验合法域名、web-view业务域名、TLS版本以及HTTPS证书”这样开发阶段就可以用http://127.0.0.1:8080调试。真正部署到线上时三种常见的选择云服务器阿里云/腾讯云前端小程序走正式域名后端Nginx转发到8080端口。微信云托管直接把Spring Boot项目做成Docker镜像部署省去服务器购买和域名备案适合不想折腾的学生。内网穿透只用于演示不稳不推荐答辩当天用。我最后是买了台低配轻量服务器Ubuntu MySQL Redis Nginx。代码用mvn package打成jar包systemctl做服务守护域名备案流程大约两周所以这些准备工作要提前做别等答辩前一周才想起来。4. 实操从零跑通这个毕设项目4.1 环境准备与项目结构导入要复现这个项目你需要以下几样东西微信开发者工具稳定版即可JDK 1.8 或 11Maven 3.6MySQL 5.7 或 8.0Redis用于存Token没有Redis可以改成MySQL表项目下载解压之后目录结构分两部分project/ ├── wx-miniapp/ # 微信小程序前端 │ ├── pages/ │ ├── components/ │ ├── utils/request.js │ └── app.js └── server/ # Java Spring Boot 后端 ├── src/main/java ├── src/main/resources/application.yml └── pom.xml先用IDEA打开server目录等待Maven下载依赖。打开application.yml修改三处MySQL账号密码、Redis地址、微信小程序AppID和AppSecret。server: port: 8080 spring: datasource: url: jdbc:mysql://localhost:3306/volunteer_association?useUnicodetruecharacterEncodingutf8mb4serverTimezoneAsia/Shanghai username: root password: 你的数据库密码 redis: host: localhost port: 6379 wechat: appid: 你的AppID secret: 你的AppSecret第一次启动前先执行项目里的sql/init.sql建库、建表、插入默认管理员账号默认账号是admin密码admin123记得上线前改。启动后端看到Tomcat started on port 8080就说明成功了。4.2 小程序端配置与登录流程联调微信开发者工具导入wx-miniapp目录然后在app.js里修改全局配置// app.js globalData: { baseUrl: http://127.0.0.1:8080, token: wx.getStorageSync(token) || }这里的baseUrl就是后端接口地址。在utils/request.js中封装统一的请求函数每次请求头带Authorization: Bearer token后端拦截器通过这个header校验身份。联调登录时用测试号更方便。微信公众平台申请小程序需要个人身份认证审核一般一天内通过。如果在开发阶段没有AppID也可以在开发者工具里用“测试号”——工具支持一键申请测试号AppID形如wx开头的一串字符能正常跑通wx.login()并换取code。测试号申请路径微信开发者工具 → 详情 → 基本信息 → 测试号 → 点击“申请”。申请完成后把测试号AppID填到后端application.yml的wechat.appid里。注意测试号的AppSecret在“开发者ID”页面里和AppID放在一起复制的时候不要漏字符。第一次进入小程序会走登录逻辑正常情况下会看到控制台打出[auth] login success。如果一直失败先确认后端日志看是code2session返回的errcode是什么40013AppID无效检查是否填错。40125AppSecret无效重置后重新复制。40029code无效或已过期重新调wx.login()。4.3 主要业务链路演示发布活动到报名签到为了验证系统跑通了我习惯走一遍完整业务链路用管理员账号登录进入“我的 → 管理员入口 → 发布活动”填好信息提交。活动状态变成“待审核”。再用一个管理员账号进入活动管理列表点击“通过”。切回普通志愿者账号首页往下拉能刷出这个新活动。点进详情 → 点击“报名”提示“报名成功”。回到“我的报名”列表能看到该活动卡片。活动开始后管理员生成签到二维码志愿者扫描签到。进入个人中心发现累计志愿时长增加了。如果每一步都能正常走通你的核心链路就完全没问题了。我排查的时候发现的最典型问题是活动列表“加载不出来”原因基本都是数据库时间字段格式问题——后端的LocalDateTime序列化默认带T前端new Date()解析后显示NaN-NaN-NaN解决方式是后端配置统一的时间格式化器Bean public Jackson2ObjectMapperBuilderCustomizer jacksonCustomizer() { return builder - builder.simpleDateFormat(yyyy-MM-dd HH:mm:ss); }5. 常见问题与排查技巧实录5.1 真机预览常见失败原因开发工具里跑得好好的一真机预览就白屏或者请求失败这个问题我身边不下五个同学遇到过。总结下来最常见的是这些没有在真机上开启调试模式真机预览时右上角胶囊按钮 → 打开调试否则网络请求可能被拦截。更准确的说法是新版本微信开发者工具预览时会默认打开vConsole如果没看到这个按钮在预览界面点“打开调试”。HTTPS证书问题真机要求所有请求必须是HTTPS不能勾选“不校验合法域名”那个选项。临时方案是“开发版”下可以用“不校验合法域名及web-view域名”但体验版和正式版不行。局域网IP不通如果你在后端配置里用了http://192.168.x.x:8080确保手机和电脑在同一WiFi下且防火墙放行了8080端口。Windows自带防火墙会拦截外部访问需要入站规则里放行Java进程或8080端口。5.2 并发报名场景下的数据正确性如果社团活动比较火比如“迎新志愿者招募”一晚上可能有一两百人同时报名。就算毕设数据量不大但这个逻辑bug一旦被答辩老师发现会很减分。我在开发初版的时候用的是“先查后插”// 错误示例 int count registrationMapper.countByActivity(activityId); if (count activity.getMaxCount()) { throw new BusinessException(名额已满); } registrationMapper.insert(registration);这样写的隐患在于两个请求同时通过count判断时都认为名额没满然后都执行插入结果超员。正确做法是用数据库原子更新或者加事务锁Transactional(rollbackFor Exception.class) public void signUp(Long activityId, Long memberId) { // 乐观锁剩余名额大于0时才能更新成功 int rows activityMapper.decreaseRemainCount(activityId, 1); if (rows 0) { throw new BusinessException(手慢了名额已被抢完); } registrationMapper.insert(...); }decreaseRemainCount对应SQL就是UPDATE activity SET remain_count remain_count - 1 WHERE id #{id} AND remain_count 0。更新行数为0说明没有剩余名额直接抛业务异常回滚事务。这套方案代码改动量小并发安全也够用。5.3 小程序端“加载中”卡住的问题树排查法页面一直转圈是开发微信小程序最让人烦的问题。我的排查顺序基本固定看后端日志是否收到请求。如果后端没收到看前端控制台报的什么错——最常见是request:fail说明请求根本没发出去或域名被拦截。如果后端收到了但返回异常看是不是数据库连接失败、空指针、或者SQL语句问题。把异常栈贴到搜索引擎基本能解决90%的问题。另一个隐蔽问题是wx.request的timeout默认是60秒如果后端接口首次启动时初始化比较慢比如MyBatis-Plus第一次解析SQL60秒内没返回就会超时。建议前端设置timeout: 1000010秒并在失败回调里提示“网络异常请稍后重试”而不是一直等。6. 毕设答辩亮点与扩展方向我的建议6.1 如何在答辩时把项目讲出“含金量”代码写完只是第一步答辩时的表达方式和准备的材料同样关键。我的体会是不要花太多时间演示“点击登录、点击查看列表”这些基础功能重点是讲清楚你“解决了什么问题”。比如你实现了乐观锁防超卖就讲这个场景系统在12月5日晚上8点开放“冬季社区敬老活动”报名同时有30名志愿者点击报名。由于报名接口采用了数据库原子化扣减剩余名额UPDATE ... WHERE remain_count 0实际只有25名能成功占名额剩余5名会收到“名额已满”的提示不会出现超报。这样一段话既点出了技术方案又展示了业务思考比干巴巴地念代码强得多。6.2 稳定的项目扩展方向如果毕设做完还有余力或者想让项目更有竞争力可以朝下面几个方向扩展数据可视化大屏在小程序端加一个“志愿数据看板”用Canvas或ECharts画图——活动参与趋势、各学院志愿总时长TOP10、活动类型占比。这块做好了视觉冲击力很强也方便从“管理系统”升级为“数字化工具”。消息提醒接入微信订阅消息活动审核通过时给管理员发通知活动开始前1小时给已报名志愿者发提醒。这个功能实用性强代码量也不大但需要个人小程序有订阅消息模板权限。Excel导出后端用EasyExcel把活动报名名单、志愿时长导出成Excel方便协会负责人交给指导老师归档这个功能在真实使用场景里是高频需求。6.3 一个容易被忽略的收尾工作上线前记得把数据库里默认的管理员密码改掉把微信小程序的AppSecret从代码里拿出来放到后端的配置中心或者环境变量中。真正的安全问题不是“AppSecret泄露会怎样”而是“代码传到GitHub/Gitee上之后所有人的搜索都能扫到你的密钥字符串”。我在GitHub上见过太多带密钥的毕设代码了这也是很多同学被安全团队点名的主要原因。如果代码要公开分享至少要在压缩包里放一份README.md里面写明部署步骤、默认账号、注意事项再附上数据库脚本。这样同学、老师、甚至以后的学弟学妹下载之后都能顺畅跑起来你自己的口碑也能攒下一波。这个项目后续还可以加的功能很多比如年度优秀志愿者评选、活动心得留言板、协会经费报销审批流程等。核心骨架都搭好了每加一个模块都是对现有模式的一次复用真正跑起来迭代之后你会发现自己对前后端联调、数据建模、接口设计都有了更具体的体感。这也是毕设除了拿学分之外真正的收获所在。
返回列表