恒美微站 Logo 恒美微站
  • 首页
  • 关于我们
  • 建站服务
  • 主题模板
  • 案例展示
  • 资讯中心
  • 联系我们

Spring Boot 社区卫生服务站疫苗接种预约系统设计与实现

  • 首页
  • 资讯中心
  • /
  • Spring Boot 社区卫生服务站疫苗接种预约系统设计与实现

相关资讯

Themida 2.x WinLicense专用脱壳工具集:VM指令追踪与OEP精确定位 2026/10/14 3:42:57
JavaScript 深拷贝和浅拷贝有什么区别?structuredClone 能替代 JSON 拷贝吗? 2026/10/14 3:37:57
工业上位机实战:工控机选型、KEPServerEX采集与MySQL存储全解析 2026/10/14 3:37:57

最新资讯

构建数学解题Agent:从LLM局限到工具调用与验证优先架构
C++类型转换详解:原理、实践与陷阱
B2B电商平台银联电子支付实战接入指南
Rabbit health check failed排查:从健康检查原理到连接配置修复
亲测2026最新10款免费降ai率工具(附工具优缺点对比图)
MySQL复合查询实战:JOIN、子查询与HAVING的正确打开方式

今日推荐

IBM Verify Identity Access 修复 22 个漏洞:两个 9.8 严重 RCE 无需认证
小区物业管理系统
小型超市仓库管理系统

本周热门

UE动画修改实战:从资产编辑到重定向与蒙太奇驱动
统计随机数生成器攻击下的KLJN安全密钥交换协议Matlab仿真
政务API安全治理:资产测绘、低代码编排与行标对标实践

本月精选

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证
2026 大模型集体涨价:用 Python 做企业 Token 成本测算与选型避坑(附配置)

Spring Boot 社区卫生服务站疫苗接种预约系统设计与实现

发布时间:2026/10/14 3:42:57
Spring Boot 社区卫生服务站疫苗接种预约系统设计与实现 Spring Boot 社区卫生服务站疫苗接种预约系统这个标题我一看就觉得是典型的毕设或课程设计项目“附源码”三个字直接暴露了它的出处。但平心而论这类系统在社区医疗数字化里算是一个特别典型的业务场景背后的需求逻辑一点都不简单——库存管理、号源分配、时间冲突校验、用户通知每一样都值得好好拆一拆。尤其这两年公共卫生服务越来越强调“预约制”社区卫生服务站要做疫苗接种的规范化管理光靠电话登记和纸质台账早就撑不住了。这篇文章就以这个项目为例从业务设计、技术选型、数据库建模到核心代码实现按照我实际开发这类系统的思路完整走一遍顺便把源码里容易踩的坑也一起说清楚。适合正在做 Spring Boot 毕设的同学也适合想了解中小型预约系统怎么落地的小伙伴参考。1. 业务设计与整体方案1.1 社区卫生服务站的预约痛点先别急着写代码我们把场景还原一下。社区卫生服务站的服务半径通常覆盖周边几个小区服务的重点人群是老人、儿童和慢性病患者。疫苗接种这件事有几个让工作人员头疼的典型问题接种时间高度集中上午九点到十一点是高峰期排队扎堆现场秩序不好维持。疫苗库存管理靠手工台账哪种疫苗还剩多少支、哪天到期、哪些人该接种第二剂全靠人脑记。漏种和迟种现象严重工作人员没法主动通知家长“该带孩子打第二针了”。纸质登记表事后统计困难上级要求上报接种数据时需要人工翻表。这些问题放到一起其实就是预约系统的核心业务价值所在把疫苗接种从“现场排队、手工登记”变成“线上预约、库存联动、到期提醒”。这样一个系统能解决的问题不是“做一个网站交作业”而是真真切切能提升社区卫生服务站的运转效率。这个项目的定位是“小型、轻量、可落地”所以不要一上来就设计微服务架构、消息队列、分布式事务。一个 Spring Boot 单体应用加 MySQL 数据库配合 Redis 做缓存和防并发已经能覆盖这类站点的全部需求。架构过度设计反而是问题会增加部署和维护成本对社区卫生服务站的运营人员来说也不友好。1.2 系统角色与核心业务流程我把这个系统的用户划分为三类角色每个角色的诉求完全不同居民用户注册登录后查疫苗、预约、取消预约、查看接种记录和公告。接种工作人员管理可预约的疫苗批次、审核预约单、核销接种、录入接种记录。系统管理员维护用户权限、管理公告、查看统计数据、配置站点基础信息。核心业务流其实就一条线用户选择疫苗和日期 - 系统检查该时段剩余号源 - 生成预约记录并占用一个号源 - 用户按时间到站接种 - 工作人员核销并录入接种信息。这条线看起来简单但每个环节都有细节比如剩余号源怎么算、取消预约后号源怎么释放、一个用户同时段能不能重复预约这些都是在写代码之前就要定清楚的规则。1.3 项目的完整功能清单我把这套系统的功能点整理成了一张表方便后续对照开发模块面向角色核心功能用户登录注册居民手机号注册、密码登录、身份信息维护疫苗信息浏览居民查看疫苗名称、适用人群、接种剂次、库存状态在线预约居民选择接种点、疫苗、日期与时间段提交预约预约记录管理居民查看预约详情、取消未核销的预约接种记录查询居民查询历史接种记录与下一剂到期时间公告通知居民查看站点公告与疫苗到货通知号源与库存管理工作人员设置每日可预约人数、疫苗库存上下限预约核销工作人员扫码或输入预约号完成现场核销统计报表管理员按日期、疫苗统计预约量与接种量功能清单定到这个粒度已经足够指导数据库表设计和接口划分了。再往下细化就是对着表结构写代码的事。2. 技术选型与项目结构2.1 技术栈选择的逻辑Spring Boot 在中小型管理系统里几乎是统治级的存在尤其是在毕设和中小公司项目中。这个项目选型我拆开说Spring Boot 2.7.x 或 3.x主框架。选 2.7 是因为兼容性稳网上资料也多排错容易选 3.x 则更贴近新版特性但要注意部分老依赖不兼容。MyBatis-Plus数据库访问层。单表 CRUD 不用写 SQL分页、条件构造器都是现成的开发效率比纯 MyBatis 高很多。这个项目业务复杂度和 SQL 复杂度都不高用 MyBatis-Plus 非常合适。MySQL 5.7 或 8.0关系型数据库存储业务数据。预计数据量也就是几万条预约记录MySQL 完全没压力。Redis用于缓存疫苗库存、每日号源余量也用来做分布式锁防止并发超卖。JWT无状态登录认证。小程序和 H5 场景都友好服务端不用存 session。Thymeleaf 或 Vue前端方案二选一。如果项目要显得“完成度高”用 Vue 前后端分离如果想省事Thymeleaf 模板直接渲染页面也可以。我后文以 Vue Axios 方式为例因为毕设答辩时前后端分离的展示效果更好。这里有个实际的考量和取舍为什么不引入 RabbitMQ 做消息通知因为这个量级的系统用不上短信和微信通知的推送频率远没有到需要消息队列的程度定时任务扫表发通知就够了。引入的中间件越多部署越重出问题的地方也越多。2.2 后端项目目录的精简设计我习惯把项目按业务模块分包而不是按技术分层分包。也就是说不要出现 controller、service、mapper 这种顶层包而是把“用户”、“疫苗”、“预约”、“公告”作为顶层模块每个模块内部再分 controller、service、mapper。这样做的理由很简单按业务切分改动一个功能的时候只进一个包代码导航更快模块边界也更清晰。典型的包结构大概是这样的com.health.vaccine ├── common // 通用类返回结果封装、异常处理、常量 ├── config // 配置类Redis、MyBatis-Plus、WebMvc、拦截器 ├── security // JWT 拦截器、登录上下文 ├── module │ ├── user // 用户管理 │ ├── vaccine // 疫苗信息管理 │ ├── appointment // 预约核心模块 │ ├── record // 接种记录 │ └── notice // 公告管理 └── utils // 日期处理、随机数、校验工具Controller 层只做参数接收和结果返回业务判断都放到 Service 层。这个原则看起来简单但很多同学写代码时会顺手把业务逻辑堆在 Controller 里导致后期测试和复用都很痛苦。做好分层是这项目能拿高分的关键之一。2.3 本地启动的准备工作源码拿到手之后不要急着点运行先把环境配好。我给一个标准的启动流程安装 JDK 8 或 11对应 Spring Boot 2.7高版本 JDK 要确认兼容。安装 MySQL 5.7创建数据库并把源码里的sql文件导入。安装 Redis默认端口 6379 即可无密码本地访问。修改application.yml里的数据库账号密码、Redis 连接配置。启动后端访问localhost:8080出现 Swagger 文档或登录接口说明启动成功。前端如果是 Vue 项目在frontend目录执行npm install后npm run dev。第 4 步是很多人容易卡住的地方数据库账号密码不对、Redis 没启动、端口被占用这三个问题占了启动失败原因的八成以上。建议先确认环境变量里的 Java 版本和配置文件的端口没有冲突。3. 数据库设计与核心表结构3.1 核心数据表的划分数据库设计是这个项目的灵魂。我根据业务功能把数据表分为“用户域”和“预约域”两部分用户域系统用户表、角色表。预约域疫苗信息表、疫苗批次库存表、预约记录表、接种记录表、公告表。表的数量控制在六张左右是比较合理的既能覆盖业务又不至于过度设计。很多毕设项目的问题恰恰是表设计得太少一张大表什么字段都往里塞导致后期扩展性很差。3.2 关键表的字段设计我挑三张核心表展开说这三张表直接决定了预约业务能不能跑通。用户表sys_user字段类型说明idbigint主键phonevarchar手机号唯一登录名passwordvarcharBCrypt 加密保存real_namevarchar真实姓名id_cardvarchar身份证号ageint年龄user_typetinyint0 居民 1 工作人员 2 管理员create_timedatetime创建时间身份证号要加唯一索引因为疫苗接种需要核实真实身份不允许同一个人注册多个账号。疫苗信息表vaccine_info字段类型说明idbigint主键vaccine_namevarchar疫苗名称categoryvarchar疫苗分类如一类、二类applicable_groupvarchar适用人群如儿童、成人dose_totalint需要接种的总剂次dose_intervalint两剂间隔天数descriptiontext疫苗说明statustinyint0 停用 1 启用疫苗和库存是两个概念一种疫苗可以有多个批次的库存批次之间有有效期差异这个设计在实际业务里很常见。预约记录表appointment_record字段类型说明idbigint主键appointment_novarchar预约编号唯一user_idbigint预约用户vaccine_idbigint疫苗vaccine_batch_idbigint疫苗批次appointment_datedate预约日期time_slotvarchar时间段如 08:30-09:30statustinyint0 待核销 1 已完成 2 已取消create_timedatetime创建时间cancel_timedatetime取消时间预约状态字段是关键所有业务流转都靠它驱动。0 表示用户预约成功了但还没去接种1 表示到站核销完成2 表示用户主动取消。后文讲的防冲突、释放号源都围绕这个状态展开。3.3 索引与事务设计思路索引设计上预约记录表要给appointment_date加普通索引统计某天预约量时用得到给user_id加索引查询个人预约列表时用得到。联合索引(appointment_date, time_slot, vaccine_id)是查询某个时间段是否约满的高频条件建议加上。事务方面预约下单这个操作必须在一个事务里完成校验用户资格和号源余量、插入预约记录、扣减号源余量三步要么全部成功要么全部回滚。这个事务是系统并发正确性的基础保障。4. 核心功能实现与关键代码解析4.1 基于 JWT 的登录鉴权实现JWT 登录在 Spring Boot 里的实现思路已经非常成熟。核心步骤是用户输入手机号和密码后端校验通过后生成 Token。Token 里存 userId 和 userType签名用 HMAC256。前端把 Token 存到本地请求时放在 Header 的Authorization字段里。后端写一个拦截器对所有需要登录的接口校验 Token 有效性。Token 的有效期我一般设置成 24 小时过期后前端跳转登录页重新登录。这里不要为了“功能丰富”去搞 refresh token 机制会增加很多复杂度实际用不上。生成 Token 的核心代码大概长这样public String generateToken(User user) { return Jwts.builder() .setSubject(user.getId().toString()) .claim(userType, user.getUserType()) .claim(phone, user.getPhone()) .setExpiration(new Date(System.currentTimeMillis() EXPIRE_TIME)) .signWith(SignatureAlgorithm.HS256, SECRET_KEY) .compact(); }拦截器里解析 Token 时要注意异常处理Token 过期、被篡改、格式错误都要分别捕获返回对应的错误码不要统一抛出一个“认证失败”否则调接口时看不出问题出在哪个环节。4.2 可预约时间段的生成规则社区接种站不是全天候接种的通常上午接种到 11 点下午到 4 点半。系统需要把一天切成若干时间段比如每个小时一段每段设置最大可预约人数这个数据由工作人员在管理端配置。生成时间段的算法很简单从当天开始往后数 7 天可配置每一天根据工作日的开始结束时间切片。比如上午08:30-09:30、09:30-10:30、10:30-11:30下午14:00-15:00、15:00-16:00、16:00-17:00每个时间段初始可预约人数设为 20 人疫苗库存和场地容纳能力决定。这个配置存储到 Redis 里key 设计为vaccine:stock:{date}:{slot}value 为剩余人数。用户预约时直接从 Redis 里扣减查询余量时也直接读 Redis响应速度比查数据库快一个数量级。这里有一个实际问题Redis 和数据库的数据一致性怎么保证我的方案是每天零点定时任务把当天的号源余量从数据库初始化到 Redis当天有用户取消预约时先更新数据库状态再递增 Redis 余量。也就是说数据库是最终一致性的保障Redis 只是热数据的加速层。这个方案应对社区卫生服务站这种量级的并发完全够用也不用引入复杂的分布式事务。4.3 预约下单与并发防超卖并发防超卖是预约系统面试必问的点。想象这个场景某个时间段剩余号源只剩 1 个两个用户同时点击预约如果没有并发控制两个人都能查到余量为 1然后都成功插入预约记录超卖就发生了。最稳妥的方案是 Redis 的原子递减命令。下单前执行Long remain redisTemplate.opsForValue().decrement(vaccine:stock: date : slot); if (remain 0) { // 余量不足回滚提示已约满 redisTemplate.opsForValue().increment(vaccine:stock: date : slot); throw new BusinessException(该时间段已约满); }因为 Redis 单线程执行命令decrement 是原子操作所以两个并发请求到达时必然一个成功一个失败从根上杜绝了超卖。这里注意扣减成功之后如果后续数据库插入失败要把 Redis 的余量加回来否则会出现“库存少了但预约没生成”的幽灵占用。这就是事务补偿的思想虽然简单但是必须做。数据库层面还有一个兜底我建议在预约记录表的(appointment_date, time_slot, user_id, status)上建唯一约束确保同一个用户在同一时间段只有一条有效预约。这样即使 Redis 逻辑漏了数据库也不会出现重复预约。4.4 取消预约与号源释放取消预约的逻辑稍有讲究。用户只能取消“待核销”状态的预约已完成和已取消的都不允许再操作。取消时先查预约记录校验状态然后更新状态为已取消再把 Redis 里对应时间段的余量加回 1。代码片段如下Transactional public void cancelAppointment(Long id, Long userId) { AppointmentRecord record appointmentMapper.selectById(id); if (record null || !record.getUserId().equals(userId)) { throw new BusinessException(预约记录不存在); } if (record.getStatus() ! 0) { throw new BusinessException(当前状态不可取消); } record.setStatus(2); record.setCancelTime(new Date()); appointmentMapper.updateById(record); // 释放号源 redisTemplate.opsForValue().increment( vaccine:stock: record.getAppointmentDate() : record.getTimeSlot() ); }这里要求 Service 方法加Transactional确保更新状态和释放号源要么都成功要么都失败。Redis 操作在事务里不是原子性的但好在状态更新是主操作Redis 释放号源失败可以通过定时任务对账来兜底。4.5 管理端核销与接种记录录入现场核销环节工作人员输入或扫码获得预约号系统查询预约记录状态为待核销的可以核销通过。核销通过后预约状态变为已完成同时往接种记录表插入一条数据记录本次接种的疫苗批次号、接种日期、接种点位、工作人员等。这里涉及一个业务细节如果某个疫苗需要接种三剂每一次到站接种都会生成一条独立接种记录三剂接种完成后用户才算完成整个免疫程序。所以接种记录表要按“次”为单位设计而不是按“人”为单位。核销接口要注意并发同一个人会不会被两个工作人员同时核销可能性很小但为保险起见核销时可以加一个乐观锁用update appointment_record set status 1 where id ? and status 0这种条件更新受影响行数为 0 说明已经被核销过了提示“该预约已核销”。5. 常见故障与排查实录5.1 预约时间冲突没拦住有同学跑测试的时候发现同一个人居然能预约两个同一时间段的不同疫苗这明显是逻辑漏洞。原因基本是校验代码写错了位置把重复性校验放在事务里但在插入完成之前没有锁保护或者只校验了预约日期没有校验时间段。我的排查经验是第一步看数据库有没有唯一索引没有就加第二步看校验逻辑是用什么条件查的“历史预约”如果查的状态包含了已取消记录就会误判冲突或漏判冲突。正确写法是查同一个用户在同一个日期同一个时间段是否存在 status0 的记录。5.2 库存扣成了负数明明上了 Redis 原子递减测试时还是会看到库存变成负数。出现这个问题的场景通常是启动时 Redis 里没有对应 keydecrement 直接创建了一个负数 key。解决办法是在生成号源时就要预置初始值不是依赖第一次 decrement。更稳妥的方式是使用 Lua 脚本一次性完成“判断存在 - 扣减 - 返回结果”多个步骤Redis 的原子性通过脚本实现比分多次调用简单可靠得多。5.3 定时任务被重复执行发了公告提醒和到期提醒之后用户收到好几条重复短信。罪魁祸首多半是定时任务没有作幂等控制。比如扫表查“明天该接种第二剂的人”一个带状态的字段没有更新下一次执行又扫到了同一批用户。解法很简单加一张任务执行记录表每次执行前检查当天是否已执行过对应的任务类型或者给目标记录加一个“已通知”标记字段。二选一都可以。5.4 前后端联调的跨域问题Vue 前端跑在 8080 端口后端跑在 9090 端口浏览器默认会拦截跨域请求。很多同学在后端写的第一个跨域配置都不完整比如只处理了 GET 请求没处理 OPTIONS 预检请求导致接口明明能通但前端一直报跨域错。我直接给你一个能用的跨域配置思路注册 WebMvcConfigurer重写 addCorsMappings 方法用allowedOriginPatterns(*)而不是allowedOrigins(*)后者在高版本 Spring 里不支持带 Cookie 的请求。注意放在公共配置类里不要写在拦截器里否则拦截器先拦截了跨域预检请求后面的跨域配置根本生效不了。5.5 日期格式化和时区混乱预约日期在后端是LocalDate传到前端变成了“2025-01-15T00:00:00”这种带 T 和时区的格式用户不能直接读。处理方案有两种一是在实体字段上加JsonFormat(pattern yyyy-MM-dd, timezone GMT8)二是在配置里统一注册一个 Jackson 配置把所有日期类型都序列化为指定格式。时区的坑也有。如果服务器时区设置成了 UTC那么new Date()取到的时间会比北京时间慢 8 个小时预约截止时间的判断就全乱了。连接 MySQL 的 URL 上最好加上serverTimezoneAsia/Shanghai把 JVM 时区和数据库时区统一成北京时间。我把这几个高频问题整理成速查表方便你对照排查现象根因解决方案跨域请求失败没处理 OPTIONS 预检用 allowedOriginPatterns 且放行预检库存出现负数Redis key 未初始就扣减初始化号源或使用 Lua 脚本重复预约同一时段唯一索引缺失加联合唯一索引通知短信重复发送任务未做幂等加已通知标记字段日期显示带 T序列化格式未指定加 JsonFormat 统一格式密码明文存储安全意识弱改用 BCrypt 加密6. 部署上线与工程化收尾6.1 从源码到可运行的系统拿到源码后最稳妥的运行顺序是先把数据库初始化跑通。源码里一般会带一个vaccine.sql把它导入 MySQL。然后改配置文件里数据库的账号密码。Redis 如果没有修改过密码保持默认即可。启动成功后用手机号注册一个居民账号再用管理员账号登录后台源码里一般会写死一个初始管理员账号先在后台添加一种疫苗配置好每日号源然后前台就能看到疫苗列表并发起预约了。这一步如果跑通了整个系统的主链路就全部打通。剩下的接种记录、公告管理、统计报表都是在主链路基础上的辅助功能代码量不大但能显著提升项目的完整度。6.2 代码规范与可维护性有些同学交上来的项目能运行但代码很难读。我在这个项目里特别强调几个容易被忽略的工程化细节统一返回结果。定义 Result 类包含 code、message、data 三个字段所有接口都返回这个结构。前端解析逻辑统一后端处理也方便。统一异常处理。用RestControllerAdvice捕获全局异常业务异常返回 50001参数校验异常返回 40001不要直接把异常堆栈返给前端。日志要打关键节点。预约下单、取消、核销这几个核心操作一定要加日志线上排查问题时没有日志几乎是寸步难行。这些细节不会在功能展示时被老师直接看到但在代码审查环节是明显的加分项。6.3 项目还能怎么扩展如果源码的主流程做好之后还有余力我建议按这个优先级做扩展微信小程序端适配居民用小程序预约比用网页方便得多这是真实场景里的硬需求。疫苗库存预警当某种疫苗剩余量低于预设阈值时自动给管理员发送通知。第二剂到期提醒定时扫描接种记录到期前三天给用户发短信提醒。接种数据导出把预约和接种数据导出成 Excel方便对接上级报表。这些扩展功能每个都不难但能体现对业务场景的深入理解答辩时讲出来效果很好。我在实际做这类系统时体会最深的一点是预约系统真正难的从来不是接口怎么写而是“号源怎么保证不超卖”、“取消后怎么不浪费”“用户操作怎么防重复”。把这些边界情况想清楚代码写起来反而是很顺的。最后再分享一个实用技巧源码跑通之后第一件事不要急着加功能先手动测一遍完整的预约-核销-取消流程把每个字段的状态变化都打印出来看一遍。这样你才能对这套系统的数据流转有个真正的掌控感后续无论是改 bug 还是扩展功能心里都会踏实很多。

关于恒美微站

恒美微站专注于为个体商户、工作室提供极简自助建站服务,让每个人都能轻松拥有专业网站。

快速链接

  • 关于我们
  • 建站服务
  • 主题模板
  • 案例展示
  • 资讯中心

服务项目

  • 可视化建站
  • 拖拽编辑
  • 主题定制
  • SEO 优化
  • 网站托管

联系方式

  • 📍 地址:北京市朝阳区建国路 88 号
  • 📞 电话:400-888-8888
  • ✉️ 邮箱:info@hmyw.cn
  • 🕐 时间:周一至周日 9:00-18:00

© 2024 恒美微站 hmyw.cn 版权所有 | 京 ICP 备 12345678 号