微信小程序医院预约挂号系统实战:Spring Boot+SSM全栈项目从搭建到二次开发

发布时间:2026/10/24 19:04:17
微信小程序医院预约挂号系统实战:Spring Boot+SSM全栈项目从搭建到二次开发 简介这份资源是面向高校计算机专业毕业设计场景的微信小程序医院预约挂号系统源码与配套文档适合正在准备毕设或课程设计的学生参考。项目以微信小程序为前端后端采用Java结合Spring Boot与SSM框架数据层使用MySQL完整覆盖用户管理、医生管理、预约挂号、通知提醒等核心模块并涉及HTTPS加密、缓存优化与高并发处理等设计思路。资源包共1个docx文件约883KB内容包含项目背景、技术选型、系统架构与关键模块实现等论述可作为论文撰写与系统搭建的参考蓝本。目前已有382人学习下载读者可从中获取完整的选题方案、技术栈说明与模块设计思路便于快速理解预约挂号系统的整体流程与实现要点为毕设开发与文档写作提供借鉴。1. 从排队三小时到手机点两下这套医院预约挂号小程序到底解决了什么早上七点去医院挂号窗口排队前面已经站了四十多人专家号放出来不到十分钟就没了——这个场景对很多患者来说太熟悉了。这套基于微信小程序的医院预约挂号系统核心目标就是把这件事搬到手机上患者打开微信就能查科室、看医生排班、在线预约后台管理员统一维护医生信息和号源。项目采用微信小程序做前端Java Spring Boot SSM 做后端MySQL 存数据是一套典型的毕业设计级全栈项目适合正在找小程序Java 后端练手项目的开发者也适合想理解预约类业务完整链路的同学。源码包里有小程序端、后台管理端和数据库脚本拿到手就能跑。2. 技术选型与整体架构为什么是 Spring Boot SSM 小程序2.1 前后端分离的 B/S 结构这个项目采用的是典型的前后端分离架构。小程序端负责页面渲染和用户交互后端提供 RESTful 接口处理业务逻辑MySQL 做数据持久化。整个数据流向是小程序发请求 → Spring Boot 接收并处理 → MyBatis 操作数据库 → 结果逐层返回。为什么选 B/S 而不是 C/S因为小程序本身就是 B/S 的变体——用户不需要安装独立客户端微信扫一下或搜一下就能打开。后端部署在服务器上更新维护只需要动服务端小程序端通过审核后自动生效这对医院这种需要频繁调整号源和科室信息的场景非常合适。2.2 Spring Boot 与 SSM 的分工这里有一个容易混淆的点Spring Boot 和 SSM 不是二选一的关系。SSM 指的是 Spring Spring MVC MyBatis 这套组合而 Spring Boot 是在此基础上做了自动配置和起步依赖的封装。实际项目里底层用的还是 Spring 的 IoC 容器、Spring MVC 的请求映射、MyBatis 的 SQL 映射只是 Spring Boot 帮你省掉了大量 XML 配置。具体到代码层面启动类上标注SpringBootApplicationController 层用RestController和RequestMapping定义接口Service 层用Service注入业务逻辑Dao 层用Mapper标注 MyBatis 接口。这种分层方式在中小型项目里非常常见结构清晰后续加模块也方便。2.3 数据库选型与核心表设计MySQL 8.0 作为数据存储主要涉及几张核心表用户表存患者和admin、医生表、科室表、预约记录表、公告表。表与表之间通过外键关联比如医生表里有科室 ID 字段预约表里有用户 ID 和医生 ID。常见做法是给预约表加联合唯一索引防止同一用户对同一医生同一时段重复下单。这个细节在源码的 SQL 脚本里一般会有体现跑之前可以先看一眼建表语句。注意MySQL 8.0 默认的认证插件是caching_sha2_password如果后端连接报认证错误需要在数据库里执行ALTER USER rootlocalhost IDENTIFIED WITH mysql_native_password BY 你的密码;切换认证方式。2.4 项目目录结构一览拿到源码后先看目录结构能帮你快速定位关键文件。后端典型的 Maven 项目结构如下hospital-registration/ ├── src/main/java/com/hospital/ │ ├── controller/ # 接口层处理小程序和后台的 HTTP 请求 │ ├── service/ # 业务逻辑层 │ │ └── impl/ # 业务实现类 │ ├── mapper/ # MyBatis 数据访问接口 │ ├── entity/ # 数据库实体类 │ ├── config/ # 配置类跨域、拦截器等 │ └── HospitalApplication.java # 启动类 ├── src/main/resources/ │ ├── application.yml # 数据库连接、端口等配置 │ ├── mapper/ # MyBatis XML 映射文件 │ └── static/ # 后台管理页面的静态资源 ├── sql/ │ └── hospital.sql # 数据库建表与初始数据脚本 └── pom.xml # Maven 依赖管理小程序端的目录结构则是微信开发者工具的标准格式pages目录下按功能模块分文件夹每个页面包含.js、.wxml、.wxss、.json四个文件。app.js里通常封装了全局的请求方法app.json里配置页面路由和 tabBar。3. 环境搭建与启动从零把项目跑起来3.1 后端环境准备与数据库初始化先把后端跑通因为小程序端需要调后端接口才能看到数据。需要准备的环境JDK 1.8 或以上、Maven 3.6、MySQL 8.0、IDEA 或 Eclipse。第一步创建数据库并导入 SQL 脚本# 登录 MySQL mysql -u root -p # 创建数据库字符集用 utf8mb4支持 emoji CREATE DATABASE hospital_db DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; # 导入建表脚本 USE hospital_db; SOURCE /path/to/sql/hospital.sql;第二步修改application.yml里的数据库连接信息spring: datasource: url: jdbc:mysql://localhost:3306/hospital_db?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/Shanghai username: root password: 你的密码 driver-class-name: com.mysql.cj.jdbc.Driver这里有几个参数容易翻车serverTimezone必须设置否则 MySQL 8.0 会报时区错误characterEncodingutf8保证中文不乱码useSSL在本地开发可以设为 false 减少警告。第三步在 IDEA 里以 Maven 项目导入等依赖下载完成后运行启动类。控制台出现Started HospitalApplication in x.x seconds就说明后端起来了默认端口一般是 8080。3.2 小程序端配置与联调小程序端用微信开发者工具打开。导入项目后第一件事是改请求地址。在app.js或封装的request.js里把 baseUrl 改成你本机的地址// app.js 中全局请求配置 const BASE_URL http://localhost:8080/api; const request (url, method, data) { return new Promise((resolve, reject) { wx.request({ url: BASE_URL url, method: method, data: data, header: { content-type: application/json }, success: res resolve(res.data), fail: err reject(err) }); }); };开发阶段需要在微信开发者工具里勾选「不校验合法域名」否则 localhost 的请求会被拦截。上线时才需要配置 HTTPS 域名并备案。3.3 后台管理端的访问后台管理端一般是集成在后端项目里的静态页面启动后端后直接访问http://localhost:8080/admin或类似路径。默认管理员账号密码通常在 SQL 脚本的初始数据里常见的是 admin/123456。登录后能看到医生管理、科室管理、预约管理、公告管理等菜单。3.4 启动顺序与验证清单正确的启动顺序是MySQL → 后端服务 → 小程序端。验证时按这个清单走一遍检查项预期结果失败时看哪里数据库连接启动无报错application.yml 的 url/密码后端接口浏览器访问 /api/dept/list 返回 JSONController 映射路径小程序首页科室列表正常加载开发者工具 Network 面板预约流程能选医生、选时段、提交成功预约表是否有新记录后台登录能进入管理界面初始账号密码是否正确4. 核心模块拆解预约挂号从选科室到下单的完整链路4.1 科室与医生列表接口小程序首页加载时第一步是拉取科室列表。后端对应的 Controller 方法大致长这样RestController RequestMapping(/api/dept) public class DeptController { Autowired private DeptService deptService; // 查询所有科室按排序字段升序 GetMapping(/list) public Result list() { ListDept depts deptService.listAll(); return Result.success(depts); } // 根据科室ID查医生列表 GetMapping(/doctors/{deptId}) public Result doctors(PathVariable Integer deptId) { ListDoctor doctors deptService.getDoctorsByDept(deptId); return Result.success(doctors); } }GetMapping对应小程序端的 GET 请求PathVariable把 URL 里的科室 ID 绑定到方法参数。返回的Result是统一响应封装包含 code、msg、data 三个字段前端根据 code 判断成功与否。MyBatis 的 XML 映射里查医生列表的 SQL 一般会关联科室表select idgetDoctorsByDept resultTypecom.hospital.entity.Doctor SELECT d.*, dept.name AS deptName FROM doctor d LEFT JOIN dept ON d.dept_id dept.id WHERE d.dept_id #{deptId} AND d.status 1 ORDER BY d.level DESC /selectstatus 1过滤掉已停诊的医生ORDER BY d.level DESC让高级职称的医生排在前面。这些细节在源码里不一定完全一样但思路是通用的。4.2 预约下单的业务逻辑预约是整个系统的核心。用户选好医生和时段后小程序提交预约请求后端需要做几件事校验该时段是否还有余号、检查用户是否重复预约、扣减号源、生成预约记录。Service public class AppointmentServiceImpl implements AppointmentService { Autowired private AppointmentMapper appointmentMapper; Autowired private ScheduleMapper scheduleMapper; Override Transactional public Result makeAppointment(Integer userId, Integer scheduleId) { // 1. 查询排班信息并加行锁防止并发超卖 Schedule schedule scheduleMapper.selectForUpdate(scheduleId); if (schedule null || schedule.getRemain() 0) { return Result.error(该时段号源已满); } // 2. 检查是否重复预约 int count appointmentMapper.countByUserAndSchedule(userId, scheduleId); if (count 0) { return Result.error(您已预约过该时段); } // 3. 扣减余号 scheduleMapper.decreaseRemain(scheduleId); // 4. 生成预约记录 Appointment appt new Appointment(); appt.setUserId(userId); appt.setScheduleId(scheduleId); appt.setStatus(0); // 0待就诊 appt.setCreateTime(new Date()); appointmentMapper.insert(appt); return Result.success(预约成功); } }这段代码有几个关键点。Transactional保证扣号和插入记录在同一个事务里要么都成功要么都回滚。selectForUpdate是数据库层面的行锁防止两个用户同时抢最后一个号。实际项目里如果并发量不大用乐观锁版本号也可以但行锁更直观。4.3 个人中心与预约记录查询个人中心页面需要展示当前用户的预约记录按状态区分待就诊、已完成、已取消。后端接口根据用户 ID 查预约表关联医生和科室信息GetMapping(/my) public Result myAppointments(RequestParam Integer userId, RequestParam(defaultValue 0) Integer status) { ListAppointmentVO list appointmentService.getByUser(userId, status); return Result.success(list); }AppointmentVO是视图对象比实体类多了医生姓名、科室名称、就诊时间等字段这些通过 SQL 的 JOIN 查询直接组装避免前端多次请求。小程序端的预约记录页面用wx:for渲染列表每条记录显示医生头像、姓名、科室、预约时间和状态标签。状态标签的颜色根据 status 值动态切换待就诊是蓝色已完成是灰色已取消是红色。4.4 后台医生信息管理后台管理端的医生管理模块核心是增删改查。新增医生时需要选择所属科室上传头像填写职称和简介。后端接收表单数据后插入医生表PostMapping(/doctor/add) public Result addDoctor(RequestBody Doctor doctor) { // 参数校验 if (StringUtils.isEmpty(doctor.getName()) || doctor.getDeptId() null) { return Result.error(医生姓名和科室不能为空); } doctor.setCreateTime(new Date()); doctor.setStatus(1); doctorMapper.insert(doctor); return Result.success(添加成功); }RequestBody接收 JSON 格式的请求体前端提交时 header 要设content-type: application/json。医生头像一般存文件路径文件上传单独走一个接口存到服务器本地目录或对象存储。5. 避坑与排查跑这个项目最容易翻车的几个地方5.1 小程序请求全部失败Network 面板显示 404现象是小程序页面空白或提示网络错误开发者工具 Network 面板里每个请求都是红色。原因通常是 baseUrl 配置不对或者后端没启动。先确认后端控制台有没有报错浏览器直接访问http://localhost:8080/api/dept/list看能不能返回 JSON。如果浏览器能访问但小程序不行检查开发者工具是否勾选了「不校验合法域名」。另外注意端口号有些项目后端配的是 8081 或 9090不是默认的 8080。5.2 数据库中文乱码科室名称显示问号建库时字符集没设对。MySQL 8.0 默认字符集已经是 utf8mb4但如果 SQL 脚本里写了DEFAULT CHARSETlatin1就会出问题。解决方法是重新建库指定utf8mb4或者用ALTER DATABASE hospital_db CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;修改。连接 URL 里也要带上characterEncodingutf8。5.3 预约提交后余号没变或者出现超卖这是并发场景下的经典问题。如果扣减余号的 SQL 是UPDATE schedule SET remain remain - 1 WHERE id ?在高并发下可能出现余号变成负数。解决思路有两种一是用UPDATE schedule SET remain remain - 1 WHERE id ? AND remain 0根据影响行数判断是否扣减成功二是在 Service 层加锁用synchronized或 Redis 分布式锁。毕业设计级别用第一种就够了。5.4 后台登录后操作报 403 或跳回登录页一般是拦截器或 Spring Security 配置问题。检查拦截器有没有放行登录接口和静态资源session 或 token 有没有正确携带。如果用的是 JWT检查前端请求头里有没有加Authorization字段。有些项目在跨域配置里漏了allowCredentials导致 session 丢失。5.5 Maven 依赖下载失败或版本冲突国内网络环境下 Maven 中央仓库可能很慢在settings.xml里配阿里云镜像能解决大部分问题。如果报NoSuchMethodError或ClassNotFoundException通常是依赖版本冲突用mvn dependency:tree查看依赖树排除掉重复的旧版本。6. 二次开发改造从能跑到好用几个实用的改造方向6.1 把号源管理从手动改成排班模板原项目的号源一般是管理员手动一条条添加医生多了之后非常繁琐。我一般会改成排班模板的方式管理员设置医生的常规出诊时间比如每周一三五上午系统自动生成未来两周的排班记录。核心逻辑是用LocalDate遍历日期匹配星期几批量插入 schedule 表。这样管理员只需要维护模板号源自动生成。// 根据模板批量生成排班 public void generateSchedule(Integer doctorId, LocalDate startDate, int days) { DoctorScheduleTemplate template templateMapper.selectByDoctorId(doctorId); ListSchedule list new ArrayList(); for (int i 0; i days; i) { LocalDate date startDate.plusDays(i); // 判断该日期是否在模板的出诊星期内 if (template.getWeekdays().contains(date.getDayOfWeek().getValue())) { Schedule s new Schedule(); s.setDoctorId(doctorId); s.setWorkDate(date); s.setTotal(template.getTotalPerDay()); s.setRemain(template.getTotalPerDay()); list.add(s); } } scheduleMapper.batchInsert(list); }6.2 加一层 Redis 缓存科室和医生列表科室和医生信息变动频率很低但小程序每次打开都要请求。用 Redis 缓存这些数据设置 10 分钟过期能明显减少数据库压力。改造方式是在 Service 层加缓存逻辑先查 Redis命中就返回没命中就查数据库并写入 Redis。Spring Boot 里用Cacheable注解就能实现配合EnableCaching开启缓存支持。6.3 预约提醒用微信订阅消息替代短信原项目可能没有提醒功能或者用的是短信需要付费。微信小程序提供了订阅消息接口用户预约时授权一次到就诊前一天推送提醒。后端调用微信的subscribeMessage.send接口传入用户的 openid、模板 ID 和消息内容。这个改造不需要额外费用用户体验也更好。6.4 改造时怎么验证没改坏每次改完一个模块按这个顺序验证先跑单元测试如果有再用 Postman 调接口确认返回正确然后在小程序端走一遍完整流程最后看后台管理端数据是否同步。我自己的习惯是改数据库相关逻辑时先在测试库跑一遍 SQL确认影响行数符合预期再上代码。提示二次开发前先用 Git 建一个分支改坏了随时能回退。数据库改动也建议先备份一份 SQL。从那以后我每次拿到这类预约系统源码都先把数据库脚本单独跑一遍确认表结构和初始数据没问题再动代码。这个习惯帮我省了很多「以为是代码问题其实是数据问题」的排查时间。希望帮到你。本文还有配套的精品资源点击获取

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询