简介:这是一套面向计算机专业学生与项目实战学习者的微信小程序智慧医疗系统毕设源码,围绕医院预约挂号与信息管理场景,提供从用户端到后台管理的完整实现方案。资源包共4个文件,以3个zip源码压缩包和1个sql数据库脚本为主,分别对应小程序客户端、服务器端、项目说明及hospital_order_db数据库,整体约31.45MB,解压后可直接导入运行。系统采用SSM框架搭配JSP、HTML、CSS、JavaScript与jQuery,数据库为MySQL,基于MVC与B/S架构,开发环境涉及微信开发者工具、Eclipse或IDEA、Tomcat。功能上区分用户、医生、管理员三种角色:小程序端支持登录注册、科室与医生信息查看、新闻与留言浏览、在线预约及个人信息修改;后台端涵盖科室、医生、病人、用户、预约、新闻、留言与系统管理等模块。已有126人学习,适合作为毕设参考或课程设计练手,帮助读者快速理解医疗类小程序的业务闭环与前后端协作方式。
1. 智慧医疗毕设选型:SSM+JSP+微信小程序这套组合到底能不能打
去年帮两个学弟看毕设,一个做的是"智慧医疗系统",前端微信小程序、后端 SSM(Spring+SpringMVC+MyBatis)、管理端 JSP,数据库 MySQL,交付物是源码包加数据库脚本加说明文档。他跑起来第一句话是"这玩意儿能过答辩吗"。我的回答是:能,而且这套组合恰恰是当前高校毕设里最稳的一档,因为它把"能演示、能讲清、能改"三件事同时满足了。
智慧医疗这个题目本身不新,但它的业务闭环特别适合毕设:患者端挂号、问诊、查报告,医生端接诊、开方,管理端管科室、管医生、管药品。微信小程序负责患者侧,天然贴合"手机挂号"的真实场景;SSM 负责后端接口和事务;JSP 负责管理后台,虽然老,但页面直出、调试直观,答辩时老师一眼能看懂数据流。这套组合不追求技术时髦,追求的是你两周内能跑通、一个月内能改出自己的东西。下面按"环境怎么搭、库怎么建、接口怎么写、坑在哪"一路讲透。
2. 环境搭建与工程结构:把 SSM+JSP+小程序三端跑起来
2.1 三端分离的目录长什么样
拿到源码包,第一件事不是急着导入 IDE,而是先看清目录结构。典型的智慧医疗毕设工程会分成三块:后端 Java Web 工程(含 SSM 配置和 JSP 页面)、微信小程序工程、数据库脚本。后端一般是 Maven 结构,src/main/java放 Controller/Service/Mapper,src/main/resources放spring-*.xml、mybatis-config.xml、jdbc.properties,src/main/webapp放 JSP、静态资源和WEB-INF/web.xml。小程序工程则是pages、utils、app.js、app.json那一套。
我一般会先画一张数据流图贴在脑子里:小程序用wx.request打后端/api/xxx接口,后端 Controller 调 Service 调 Mapper 查 MySQL,返回 JSON;JSP 管理端则是浏览器直接请求.jsp或后端接口,服务端渲染后返回 HTML。两条链路共用同一套 Service 和 Mapper,这是这套架构最省事的地方——业务逻辑写一遍,两端都能用。
提示:如果源码里后端是传统非 Maven 的 Web 工程(
WebContent目录 +lib手动放 jar),别慌,导入方式换成 Eclipse 的 Dynamic Web Project 即可,逻辑完全一样。
2.2 后端环境:JDK、Tomcat、MySQL 的版本对齐
版本不对齐是新手翻车第一现场。SSM 老工程对 JDK 很敏感,常见做法是 JDK 8 + Tomcat 8.5 + MySQL 5.7,这套组合兼容性最好。如果你机器上装了 JDK 17,Spring 老版本反射会报InaccessibleObjectException,别硬刚,装个 JDK 8 切换过去。
# 查看当前 JDK 版本,确认是 1.8 java -version # 配置 JAVA_HOME(Linux/macOS 示例,Windows 在系统环境变量里改) export JAVA_HOME=/usr/lib/jvm/jdk1.8.0_xxx export PATH=$JAVA_HOME/bin:$PATH # 验证 javac -version逻辑说明:java -version输出里出现1.8.0才算对。参数上,JAVA_HOME必须指向 JDK 根目录而不是bin,Tomcat 启动脚本靠它找编译器。如果输出是17或21,去 Oracle 或 Adoptium 下个 8u 版本装上,用update-alternatives(Linux)或环境变量(Windows)切过去。
MySQL 这边,导入脚本前先建库。数据库脚本通常在sql/或db/目录下,文件名类似hospital.sql。
# 登录 MySQL mysql -u root -p # 建库并指定字符集,避免中文乱码 CREATE DATABASE hospital_db DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; # 退出后用脚本导入 mysql -u root -p hospital_db < hospital.sql逻辑说明:字符集必须用utf8mb4,因为患者姓名、病历描述里可能有生僻字甚至 emoji。参数上,utf8mb4_general_ci排序规则够用,别用utf8(三字节),否则四字节字符会插入失败。导入后执行SHOW TABLES;确认表都进来了,常见表有user、doctor、department、appointment、medical_record。
2.3 小程序端:开发者工具导入与请求域名配置
小程序工程用微信开发者工具导入,选到含app.json的那层目录。导入后第一件事是改app.js或utils/request.js里的后端地址。
// utils/request.js 典型封装 const BASE_URL = 'http://localhost:8080/hospital'; // 改成你的后端地址 function request(url, method, data) { return new Promise((resolve, reject) => { wx.request({ url: BASE_URL + url, method: method || 'GET', data: data || {}, header: { 'content-type': 'application/json' }, success: (res) => { if (res.data.code === 200) { resolve(res.data.data); } else { wx.showToast({ title: res.data.msg || '请求失败', icon: 'none' }); reject(res.data); } }, fail: reject }); }); } module.exports = { request };逻辑说明:BASE_URL是后端根路径,/hospital是 Tomcat 里的 context path,要和web.xml或 Tomcat 配置一致。参数上,header用application/json对应后端@RequestBody;如果后端用@RequestParam接收表单,改成application/x-www-form-urlencoded。开发阶段在开发者工具里勾选"不校验合法域名",否则localhost会被拦。真机调试时localhost换成电脑局域网 IP,手机和电脑连同一个 WiFi。
注意:小程序请求必须走 HTTPS 才能上线,但毕设演示阶段用开发者工具的"不校验域名"开关就够了,别在这上面耗时间。
3. 数据库设计与 SSM 分层:智慧医疗的业务表怎么落地
3.1 核心表结构与字段设计
智慧医疗的业务表不多,但关系要理清。下面这张表是我从多个同类工程里总结出的最小可用集合,字段名可按源码微调,但结构逻辑一致。
| 表名 | 作用 | 关键字段 |
|---|---|---|
| user | 患者/用户 | id, openid, name, phone, password |
| doctor | 医生 | id, name, department_id, title, intro |
| department | 科室 | id, name, description |
| appointment | 挂号预约 | id, user_id, doctor_id, appoint_time, status |
| medical_record | 病历 | id, user_id, doctor_id, diagnosis, create_time |
| medicine | 药品 | id, name, price, stock |
appointment.status是关键,一般用 0 待就诊、1 已就诊、2 已取消。user.openid存微信登录返回的唯一标识,这是小程序登录的核心字段。设计时注意外键关系:appointment.user_id关联user.id,doctor.department_id关联department.id,查询时用 JOIN 一次拿全,别在 Java 里循环查库。
3.2 MyBatis 映射与 Mapper 写法
SSM 里 MyBatis 负责 SQL 映射。典型 Mapper 接口加 XML 的组合如下。
// DoctorMapper.java public interface DoctorMapper { List<Doctor> selectByDepartment(@Param("departmentId") Integer departmentId); Doctor selectById(@Param("id") Integer id); }<!-- DoctorMapper.xml --> <mapper namespace="com.hospital.mapper.DoctorMapper"> <select id="selectByDepartment" resultType="com.hospital.entity.Doctor"> SELECT d.*, dep.name AS departmentName FROM doctor d LEFT JOIN department dep ON d.department_id = dep.id WHERE d.department_id = #{departmentId} </select> </mapper>逻辑说明:namespace必须和 Mapper 接口全限定名一致,否则启动报BindingException。resultType指向实体类,字段名和列名不一致时靠AS别名或resultMap对齐。参数上,#{}是预编译占位符,防 SQL 注入;${}是字符串拼接,只在动态排序字段这种场景用,且必须白名单校验。查询科室下医生时用LEFT JOIN而不是INNER JOIN,避免科室没医生时整个列表为空。
3.3 Service 事务与挂号并发处理
挂号是智慧医疗里唯一有并发风险的点:同一个号源被两个人同时抢。毕设层面不用上分布式锁,但@Transactional加乐观锁足够讲清楚。
@Service public class AppointmentServiceImpl implements AppointmentService { @Autowired private AppointmentMapper appointmentMapper; @Autowired private DoctorMapper doctorMapper; @Override @Transactional(rollbackFor = Exception.class) public Result book(Integer userId, Integer doctorId, Date appointTime) { // 查询该医生该时段是否已被预约 int count = appointmentMapper.countByDoctorAndTime(doctorId, appointTime); if (count > 0) { return Result.fail("该时段已被预约"); } Appointment app = new Appointment(); app.setUserId(userId); app.setDoctorId(doctorId); app.setAppointTime(appointTime); app.setStatus(0); appointmentMapper.insert(app); return Result.success("预约成功"); } }逻辑说明:@Transactional(rollbackFor = Exception.class)保证插入失败时回滚,默认只回滚RuntimeException,加上Exception更保险。参数上,countByDoctorAndTime是自定义查询,SQL 里对doctor_id + appoint_time建联合索引,否则并发下全表扫描会拖慢。严格说这种"先查后插"仍有竞态窗口,毕设答辩时你可以主动提"生产环境会用唯一索引或分布式锁",反而是加分项。
提示:给
appointment表的(doctor_id, appoint_time)加唯一索引,插入冲突时捕获DuplicateKeyException返回友好提示,这是最省事的防重方案。
4. 微信小程序端对接:登录、挂号、报告查询三条主链路
4.1 微信登录换 openid 的完整流程
小程序登录不是拿手机号,而是wx.login拿 code,后端拿 code 换 openid。这是热词里"微信小程序登录获取手机号"的前置步骤,手机号需要额外授权,毕设里用 openid 标识用户就够了。
// pages/login/login.js wx.login({ success: (res) => { if (res.code) { wx.request({ url: BASE_URL + '/api/user/login', method: 'POST', data: { code: res.code }, success: (r) => { wx.setStorageSync('token', r.data.data.token); wx.setStorageSync('userId', r.data.data.userId); } }); } } });逻辑说明:res.code只能用一次,五分钟过期。后端拿到 code 后调用微信接口换openid和session_key,再生成自己的 token 返回。参数上,wx.setStorageSync把 token 存本地,后续请求在 header 里带上。注意session_key绝不能下发到小程序端,它只在后端用。
4.2 挂号页面与科室医生联动
挂号页面的交互是"选科室 → 拉医生列表 → 选时段 → 提交"。科室和医生用两级联动,避免一次拉全量数据。
// 选科室后加载医生 onDepartmentChange(e) { const deptId = e.detail.value; request('/api/doctor/list?departmentId=' + deptId, 'GET').then(list => { this.setData({ doctors: list, selectedDept: deptId }); }); }逻辑说明:e.detail.value是 picker 选中的索引或值,取决于range-key配置。参数上,接口用 GET 带 query 参数,后端@RequestParam接收。列表渲染用wx:for,每个医生卡片绑定>// 统一返回给前端的日期格式 @JsonFormat(pattern = "yyyy-MM-dd HH:mm", timezone = "GMT+8") private Date createTime;
逻辑说明:@JsonFormat注解控制 Jackson 序列化格式,不加的话前端拿到的是时间戳。参数上,timezone = "GMT+8"必须写,否则服务器时区不对会差 8 小时。JSP 端展示用 JSTL 的<fmt:formatDate>,格式保持一致,避免患者和医生看到的时间对不上。
注意:JSP 页面里如果用了
<%@ page contentType="text/html;charset=UTF-8" %>,数据库连接串也要带useUnicode=true&characterEncoding=utf8,两头都设才不会乱码。
5. 避坑与排查:这套毕设工程最容易翻车的 5 个点
5.1 启动报 404,接口一个都访问不到
现象:Tomcat 起来了,访问http://localhost:8080/hospital/api/doctor/list返回 404。原因通常是web.xml里 DispatcherServlet 的url-pattern配成了/但 Spring 配置没扫到 Controller 包,或者 context path 不对。解决:先看 Tomcat 启动日志有没有Root WebApplicationContext initialized,再确认spring-mvc.xml里<context:component-scan base-package="com.hospital.controller"/>的包名和实际一致,最后核对访问路径里的/hospital是不是web.xml里配的display-name或 Tomcat 部署名。
5.2 中文乱码,患者姓名变成问号
现象:小程序提交的中文姓名存进数据库变成???。原因有三层:请求编码、数据库连接编码、表字段编码。解决:web.xml加CharacterEncodingFilter设UTF-8;JDBC URL 加useUnicode=true&characterEncoding=utf8;建库建表用utf8mb4。三层缺一层都会乱,按顺序排查。
5.3 小程序真机请求失败,开发者工具却正常
现象:模拟器里接口通,真机预览报request:fail。原因是真机不认localhost,且默认校验域名。解决:把BASE_URL换成电脑局域网 IP(如http://192.168.1.100:8080/hospital),手机和电脑同一 WiFi,开发者工具里勾选"不校验合法域名"。如果还不行,检查电脑防火墙有没有拦 8080 端口。
5.4 MyBatis 报 Invalid bound statement
现象:启动或调用时报Invalid bound statement (not found)。原因是 Mapper XML 没被扫描到,或namespace和接口对不上。解决:确认mybatis-config.xml或 Spring 配置里mapperLocations指向classpath:mapper/*.xml,且 XML 文件确实编译进了target/classes。IDEA 里有时 XML 放在java目录下不会被打包,挪到resources下最稳。
5.5 挂号重复提交,同一时段出现两条记录
现象:用户手快点了两次提交,数据库出现两条同时段预约。原因是前端没防抖,后端没防重。解决:前端按钮点击后置disabled,后端在appointment表加(doctor_id, appoint_time)唯一索引,插入时捕获DuplicateKeyException返回"请勿重复预约"。这是最省事也最可靠的双保险。
6. 从能跑到能答辩:二次开发与验证的几个实用技巧
把工程跑通只是起点,答辩老师最爱问的是"你改了什么"。我的习惯是拿到源码后先做三件事:换掉默认的登录账号密码、给核心表加两三个自己的字段、把某个页面的交互重写一遍。这三步做完,你对整套代码的掌控就从"能跑"变成"能讲"。
具体技巧上,验证后端接口别只靠小程序,用 Postman 或 curl 直接打接口最快。
# 测试挂号接口 curl -X POST http://localhost:8080/hospital/api/appointment/book \ -H "Content-Type: application/json" \ -d '{"userId":1,"doctorId":2,"appointTime":"2025-06-01 09:00"}'逻辑说明:直接打接口能排除小程序端的干扰,快速定位是后端问题还是前端问题。参数上,-H指定 JSON 头,-d是请求体,返回的 JSON 里看code和msg判断成败。如果返回 500,去看 Tomcat 日志的堆栈,比在小程序里猜快十倍。
二次开发时,我一般会挑"科室管理"这个模块练手,因为它增删改查齐全、逻辑简单、改完立刻能在 JSP 后台看到效果。加一个"科室简介"字段,从数据库到实体到 Mapper 到 Controller 到 JSP 页面走一遍,整套 SSM 的链路就彻底通了。改完记得同步更新数据库脚本,答辩时老师要看你的 SQL 文件,字段和代码对不上会扣分。
最后一个血泪经验:源码包里的说明文档一定要自己读一遍再改代码,很多工程在README里写了默认端口、默认账号、依赖的特殊 jar,跳过这步直接改,后面报错会怀疑人生。我见过太多人卡在"数据库连不上",最后发现是文档里写了密码不是root。这套智慧医疗毕设的技术栈不新,但胜在完整、可讲、可改,把上面这些跑一遍,你手里就有一个能撑起答辩的项目了。希望帮到你。
本文还有配套的精品资源,点击获取