ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

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

微信小程序医院预约挂号系统实战: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 配置。

具体到代码层面,启动类上标注@SpringBootApplication,Controller 层用@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 'root'@'localhost' 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?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai username: root password: 你的密码 driver-class-name: com.mysql.cj.jdbc.Driver

这里有几个参数容易翻车:serverTimezone必须设置,否则 MySQL 8.0 会报时区错误;characterEncoding=utf8保证中文不乱码;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() { List<Dept> depts = deptService.listAll(); return Result.success(depts); } // 根据科室ID查医生列表 @GetMapping("/doctors/{deptId}") public Result doctors(@PathVariable Integer deptId) { List<Doctor> doctors = deptService.getDoctorsByDept(deptId); return Result.success(doctors); } }

@GetMapping对应小程序端的 GET 请求,@PathVariable把 URL 里的科室 ID 绑定到方法参数。返回的Result是统一响应封装,包含 code、msg、data 三个字段,前端根据 code 判断成功与否。

MyBatis 的 XML 映射里,查医生列表的 SQL 一般会关联科室表:

<select id="getDoctorsByDept" resultType="com.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 </select>

status = 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) { List<AppointmentVO> 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 CHARSET=latin1就会出问题。解决方法是重新建库指定utf8mb4,或者用ALTER DATABASE hospital_db CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;修改。连接 URL 里也要带上characterEncoding=utf8。

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); List<Schedule> 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。

从那以后我每次拿到这类预约系统源码,都先把数据库脚本单独跑一遍确认表结构和初始数据没问题,再动代码。这个习惯帮我省了很多「以为是代码问题其实是数据问题」的排查时间。希望帮到你。

本文还有配套的精品资源,点击获取

返回列表