做计算机毕业设计的时候,我选了一个特别能体现工程能力的题目:基于微信小程序的HPV疫苗预约与抢苗系统。Java后端 + SpringBoot框架 + 微信小程序前端,这套组合在答辩里非常能打,因为它天然覆盖了从普通CRUD到高并发扣库存的技术层次。
HPV疫苗预约和普通挂号系统不一样,它有两个完全不同的业务场景:一个是常规的预约排号,另一个是高并发下的“抢苗”。抢过九价的人都知道,放苗那一刻,系统卡顿、转圈、提示“已约满”是常态。很多同学会把这种系统做成一个普通的增删改查,答辩时被老师问一句“抢苗瞬间你是怎么保证不超卖的”就答不上来。这篇文章把我当时从需求分析到数据库设计、后端接口、小程序端实现,再到压测踩坑的完整过程写出来,给正在做类似选题的同学一个可以直接参考的路线。
1. 为什么HPV疫苗预约系统比普通挂号系统难做
1.1 九价疫苗的供需矛盾带来的业务场景
先理清业务背景。HPV疫苗分二价、四价、九价,其中九价适用年龄是16到26岁女性,供应量长期紧张。很多城市的社区医院放苗周期不固定,每月放一次,每次几十到几百支,但排队的人有几万。这个供需矛盾决定了系统不能只做“预约”,还要做“抢苗”。
抢苗意味着什么?意味着某个时间点(比如上午10点整)大量用户同时点击“立即预约”,后端在同一时刻收到几千上万个请求。如果还是普通挂号那种“先查库存,再插入订单”的写法,数据库很快就会被打崩,而且会出现超卖——库存只剩1支,但10个人都预约成功了。
我一开始也天真地觉得,毕设嘛,把页面做出来,能操作就行。后来整理需求的时候才意识到,预约和抢苗是两种截然不同的业务模型,需要分开设计。普通预约可以允许用户选择时间段、提前几天约;抢苗则是“到点开放、先到先得、瞬间并发”。
1.2 预约与抢苗是两种截然不同的业务模型
普通预约的核心是“资源编排”,关注的是时间段的冲突检测,比如一个接种点一天开放100个号,上下午各50个,你不能重复预约同一个时间段。抢苗的核心则是“库存竞争”,关注的是扣减的原子性和并发控制,你不能把最后一个名额同时给两个人。
这个区别直接影响技术方案。我做的时候把两个流程拆开了:
- 普通预约:走数据库事务,先查疫苗批次剩余数量,大于0就插入预约记录并扣减库存,用乐观锁控制并发。
- 抢苗:走Redis预扣库存 + 异步落库,用Lua脚本保证“判断库存 + 扣减”的原子性,避免超卖。
具体怎么实现,后面章节会详细讲。先记住一个结论:HPV疫苗预约系统的核心难点不在CRUD,而在库存扣减的并发安全。 这个点抓住了,论文的核心创新点、答辩的亮点就都有了。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 技术选型与整体架构:从毕业设计答辩角度反推
2.1 为什么是SpringBoot + 微信小程序
先说为什么选微信小程序。HPV疫苗接种群体以年轻女性为主,微信公众号里预约、扫码、消息提醒都是刚需,小程序天然免安装、用完即走。从毕设角度讲,小程序端也是一个完整的独立前端项目,比纯网页后端要丰富很多,开题和答辩都有东西可展示。
后端选SpringBoot理由就很简单了:Java生态成熟,SpringBoot自动配置省去一堆XML配置,内嵌Tomcat一键启动,非常适合毕设阶段快速交付。而且Java在后端招聘市场占有率一直很高,做完这个项目写进简历,面试官问到高并发、缓存、事务这些点,你都有实际场景可以聊。
我用的具体版本是:
- JDK 1.8(兼容性最好,答辩演示不出问题)
- SpringBoot 2.7.x
- MyBatis-Plus 3.5.x
- Redis 6.x(Windows本地测试可以用,演示建议用Linux环境)
- MySQL 5.7 / 8.0 都可以
- 微信小程序原生开发(不引入uniapp,减少不必要的复杂度)
- 若依框架(可以选择不用,自己搭简单权限就行)
提示:如果你的电脑内存只有8G,建议JDK1.8 + SpringBoot 2.7.6,别追最新版,SpringBoot 3.x必须配JDK17,有些老版本的MyBatis-Plus插件不兼容,查起问题来很耽误时间。
2.2 系统整体架构与模块划分
这个项目虽然是毕设,但我还是按生产环境的分层思想去设计的。整体分为四层:
| 层级 | 技术载体 | 职责 |
|---|---|---|
| 小程序端 | WXML / WXSS / JS | 用户登录、疫苗浏览、预约操作、抢苗页面、订单管理 |
| 接入层 | SpringBoot Controller | 参数校验、鉴权、接口路由 |
| 业务层 | SpringBoot Service | 预约逻辑、库存扣减、消息通知、事务控制 |
| 数据层 | MySQL + Redis | 用户数据、疫苗库存、预约订单、缓存数据 |
模块拆分上,我的包结构是:
code复制com.hpv.vaccine
├── c
