简介这是一个基于SSM框架与MySQL的医院分诊管理系统完整源码面向JavaWeb学习者、毕业设计或课程设计人群用于理解医生分诊叫号、患者信息维护、科室管理等业务流程。系统包含可运行的前后端与数据库文件能实现分诊管理、患者管理、科室管理、系统监控等功能并支持在线叫号与就诊状态统计。压缩包共2000个文件约43.65MB其中包含3341个png页面素材、182个js脚本、91个jar依赖、83个class编译文件、76个java源码、34个jsp页面以及3个sql数据库脚本等类型覆盖前端页面、后端逻辑、依赖库与数据库初始化便于直接导入工程学习。已有286人学习下载。适合需要完整SSM项目参考、理解医院分诊场景并希望基于现有代码二次开发的读者借助项目中完整的业务模块划分与数据库脚本可快速梳理流程并运行验证。1. 医院分诊管理系统能落地吗先说清楚这个 ssmmysql 项目解决了什么这是一份真正能跑通的医院分诊管理系统源码后端用 SSMSpring SpringMVC MyBatis数据库用 MySQL前端页面和日期控件都带全了。它不是只写了个登录页的课程设计空壳而是把分诊、叫号、患者管理、科室管理、系统监控做成了完整闭环医生登录后点“分诊管理”能看到待分诊的患都信息选定科室后直接在线叫号患者完成就诊后状态自动推进。适合正在做 SSM 课设、需要一份完整业务参考的开发者也适合想拿现成后台快速做二开的从业者。最直接的用途就是把这套流程拆开看明白 SSM 项目里权限、分诊、状态流转到底是怎么组织的。2. 拆解分诊系统的骨架登录、权限与叫号数据流拿到源码包先别急着启动我建议先看几个关键文件UserController、RoleController、UserRealm、SimpleHibernateDao、JsonMapper。别看它们零散它们分别对应着后端的三层结构边界Controller 层接收请求Service 层处理业务Dao 层通过 MyBatis 和 MySQL 交互。HibernateDao 这个名字容易让人误以为项目用了 Hibernate其实在 SSM 项目里这通常只是一个通用 DAO 基类命名沿用 Hibernate 风格真正的持久层框架还是 MyBatis。下面按我复现时的理解把这些模块拆开讲。2.1 SSMMySQL 的选型逻辑为什么这套组合能撑住分诊场景分诊系统的核心数据量并不大一个普通医院信息科管理几百条患者记录、几十个科室单次查询和写入的压力远没到需要微服务或 NoSQL 的级别。SSM 在这种业务体量下显得非常合适Spring 负责统一管理对象和事务SpringMVC 负责把前端请求映射到 ControllerMyBatis 负责把 SQL 和 Java 方法做映射MySQL 负责持久化。三层职责清楚出问题时定位也直接。资源里已经编译好的 .class 文件正好说明了它的结构User.class 是用户实体UserController 和 RoleController 是控制层入口SimpleHibernateDao 提供通用的增删改查JsonMapper 负责把 Java 对象转成 JSON 给前端 AJAX 调用。这种组织方式现在看可能有点“老派”但对于想学 SSM 的人来说它反而比 Spring Boot 那种自动装配更透明每个 Bean 怎么创建的、每个 SQL 从哪里来翻源码就能看到。对于生产场景这套组合的边界也很明确它适合内部管理系统不适合高并发对外业务。如果是给医院做正式生产环境我一般会建议后面再套一层缓存和读写分离但在源码学习、毕业设计、内部管理系统复现这个层面SSMMySQL 完全够用。2.2 权限控制User、RoleController、UserRealm 各自的职责权限这块是这套系统里最值得看的部分。UserRealm.class 是 Apache Shiro 的核心扩展点项目里登录认证和角色授权都在这个类里实现。常见做法是让它继承 AuthorizingRealm重写两个方法public class UserRealm extends AuthorizingRealm { Autowired private UserService userService; // 登录时调用根据用户名查出用户比对密码 Override protected AuthenticationInfo doGetAuthenticationInfo( AuthenticationToken token) throws AuthenticationException { String username (String) token.getPrincipal(); User user userService.findByUsername(username); if (user null) { throw new UnknownAccountException(账号不存在); } return new SimpleAuthenticationInfo(user.getUsername(), user.getPassword(), ByteSource.Util.bytes(user.getSalt()), getName()); } // 授权时调用查询角色与权限标识 Override protected AuthorizationInfo doGetAuthorizationInfo( PrincipalCollection principals) { String username (String) principals.getPrimaryPrincipal(); SetString roles userService.findRolesByUsername(username); SetString perms userService.findPermsByUsername(username); SimpleAuthorizationInfo info new SimpleAuthorizationInfo(); info.setRoles(roles); info.setStringPermissions(perms); return info; } }密码处理那行值得多说一句SimpleAuthenticationInfo 里传入了 salt 字节源说明用户表通常有 password 和 salt 两个字段密码不是明文存储而是 MD5 加盐后保存。如果你在导入数据库后登录不上先查这两个字段的格式不要一上来就怀疑代码有 Bug。数据库里对应三张核心表sys_user、sys_role、sys_user_role。UserController 负责维护用户RoleController 负责维护角色这两张表通过中间关联表建立多对多关系。登录后 Shiro 会通过 UserRealm 加载该用户的角色和权限前端菜单再根据权限标识显示或隐藏这就实现了“分诊管理只有医生能看到系统管理只有管理员能看到”的效果。你如果想把某个权限收窄不用改代码只需要在角色管理里给该角色去掉对应权限标识。2.3 分诊主流程患者添加、科室选择、叫号、完成就诊分诊模块是整个系统的业务核心也是最值得照着做一遍完整流程的地方。从摘要描述里可以提炼出这样一条数据流先到“患者管理”里添加患者添加成功后切到“分诊管理”能看到这个患者出现在待分诊列表里选择纠正科室后点击叫号患者状态变为已叫号医生在对应科室界面执行就诊完成状态再推进到已完成。我复现时在 Controller 里看到的典型处理逻辑是这样的Controller RequestMapping(/patient) public class PatientController { Resource private PatientService patientService; RequestMapping(/add) ResponseBody public JsonResult addPatient(Patient patient) { // 0待分诊 1已分诊 2已叫号 3已完成 patient.setStatus(0); patient.setCreateTime(new Date()); patientService.insert(patient); return JsonMapper.toJsonResult(true, 患者登记成功); } }这段代码的关键是 status 字段。一个患者从登记到完成就诊就是 status 从 0 一路变到 3 的过程。前端“分诊管理”点击叫号后端其实就是一个 update 语句把 status 从 1 改成 2点击完成就诊就把 status 改成 3。“是否已经完成就诊”这个展示列本质就是 status 状态的可视化。再看分诊列表的查询 SQL这是业务里最能体现表关系的部分select idlistTriagePatients resultTypecom.example.entity.TriagePatientVO SELECT p.id, p.name, p.sex, p.age, p.dept_id, d.dept_name, p.status, p.triage_time FROM triage_patient p LEFT JOIN triage_dept d ON p.dept_id d.id where if testdeptId ! null and deptId ! AND p.dept_id #{deptId} /if if teststatus ! null AND p.status #{status} /if /where ORDER BY p.triage_time DESC /select这里用 LEFT JOIN 而不是 JOIN原因是刚登记但还没分配科室的患者 dept_id 可能是空的LEFT JOIN 能保证这类患者依然显示在分诊列表里。如果你自己在改需求要注意这个点用 INNER JOIN 会把还没选科室的患者过滤掉用户就“找不到刚添加的人”了这是一个特别常见的翻车点。科室管理的本质是维护 triage_dept 表前端加科室就是往这张表 INSERT 一条记录。系统监控部分则对应资源里的 ScheduleJobService.class这类类通常用 Quartz 或 Spring Task 跑定时任务比如每天统计各科的就诊人数、清理长期未完成的挂号记录。你可以在源码里搜一下这个类的调用处就能看到定时统计是怎么接进去的。3. 本地部署与配置从 JDK 到数据库脚本六步把系统跑起来部署 SSM 项目跟部署 Spring Boot 不一样它不是打好一个 jar 包里就启动就完事而是要管理 Web 容器、数据库脚本、配置文件三个部分。这套系统的部署顺序建议按下面几步走每一步都顺手验证一下再往下推进。3.1 环境准备与版本匹配JDK、Maven、Tomcat、MySQL最稳的组合是 JDK 1.8、Maven 3.6、Tomcat 8.5、MySQL 5.7。资源既然已经带 .class 文件开发者大概率就是用 JDK 1.8 编译的你如果用更高版本也可能能跑但排查成本会上升不建议在环境上给自己挖坑。先验证当前环境java -version mvn -v mysql --version逻辑说明这三条命令分别查看 JDK、Maven、MySQL 版本。SSM 项目常见的问题是编译版本和运行版本不一致比如用 JDK 11 编译出来的 class 放到 JDK 8 的 Tomcat 里会直接报 UnsupportedClassVersionError。如果你电脑上装的是 JDK 17我一般建议先装一个 JDK 8 并调整 JAVA_HOME再跑这个项目——这个系统的代码基本是按老式写法写的Lambda 和模块化特性用得少JDK 8 最保险。参数说明Tomcat 版本不要低于 8因为项目里可能用到了 Servlet 3.0 的异步注解MySQL 5.7 和 8.0 在连接驱动上差异比较大下面配置里会专门说明。3.2 创建数据库与导入初始数据源码包里的 SQL 文件一般命名为 xxx.sql 或 db.sql先别急着双击导入先建库再导数据避免表名冲突。推荐在命令行里操作比可视化工具更直观CREATE DATABASE IF NOT EXISTS triage_system DEFAULT CHARACTER SET utf8mb4 DEFAULT COLLATE utf8mb4_general_ci; USE triage_system; SOURCE /your/path/triage_system.sql;逻辑说明第一条语句创建数据库字符集指定为 utf8mb4这能同时兼容中文和 emoji避免出现网页上问号乱码。第二条 SOURCE 是 MySQL 命令行导入脚本的指令注意脚本里如果本身有 CREATE DATABASE 语句你前面的建库可以省略但先建库的好处是能控制字符集和权限避免脚本默认设置不符合预期。导入完成后验证一下关键表SHOW TABLES; SELECT id, username, status FROM sys_user;如果能查到用户数据说明脚本导入成功。如果查 tasys_user 为空再看一眼 SQL 脚本里有没有插入语句——有些源码故意把初始化数据放成单独文件需要一并导入。3.3 修改 jdbc.properties 并部署到 TomcatSSM 项目的数据库连接信息通常集中在 jdbc.properties位置一般在 src/main/resources 下。打开文件把连接地址、用户名、密码改成你自己的jdbc.drivercom.mysql.jdbc.Driver jdbc.urljdbc:mysql://localhost:3306/triage_system?useUnicodetruecharacterEncodingutf8 jdbc.usernameroot jdbc.passwordyourpassword参数说明driver 用的是 com.mysql.jdbc.Driver对应 MySQL 5.x 的驱动包。如果你用的是 MySQL 8.0需要换成 com.mysql.cj.jdbc.Driver并且连接地址带上 serverTimezoneAsia/Shanghai否则启动时易报时区错误。改完配置后用 Maven 打包成 warmvn clean package -DskipTests打包产物在 target 目录下一般叫 triage_system.war。把它复制到 Tomcat 的 webapps 目录启动 Tomcatcp target/triage_system.war $TOMCAT_HOME/webapps/ $TOMCAT_HOME/bin/startup.sh启动后访问系统登录页。如果页面 404先去 Tomcat 的 logs/catalina.out 看有没有部署成功如果看到报错信息是数据库相关回到 jdbc.properties 检查配置。3.4 遗留的 WdatePicker.js.bak日期控件的备份文件怎么用源码包里出现的 WdatePicker.js.bak是 My97 日期选择器插件脚本的备份文件。正常的日期插件目录下应该有一个 WdatePicker.js如果它在部署时被自动改名或损坏页面上的日期选择框就会空白或点击无响应。处理方式很直接在 WebRoot 或 webapp 的 js 目录下找到 WdatePicker.js.bak把它复制一份并重命名为 WdatePicker.js然后强制刷新浏览器缓存。不要直接删掉 .bak因为它可能包含你当前项目正在引用的版本内容删了再想找回就麻烦了。实际操作命令cd your_project/webapp/static/My97DatePicker/ cp WdatePicker.js.bak WdatePicker.js这里加 cp 而不是 mv是给自己留后悔药万一新文件有问题备份还在。部署到生产环境前建议把 .bak 移除或保留在源码包之外因为服务器上部署时多余文件不会帮你跑通功能反而可能有安全隐患。4. 避坑排查从启动失败到中文乱码的几个常见现场这一章把我的实测踩坑记录按环境、功能、数据三类整理出来。每条我都按“现象 → 原因 → 解决”来写你可以直接对照排查。4.1 环境类端口占用、MySQL 连接失败、时区报错现象一启动 Tomcat 后访问页面提示连接被重置或直接看不到服务查看日志发现端口被占用。原因Tomcat 默认 8080 端口被其他 Java 进程或其他 Web 容器占用。解决先用命令确认占用情况再决定是让项目换端口还是清理原进程netstat -ano | grep 8080 kill 占用该端口的进程如果不想杀进程直接改 Tomcat 的 server.xml 里 8080 端口为 8090再重启。无论哪种都要保证项目前端写的请求地址和实际端口一致。现象二应用启动后报 Cannot create PoolableConnectionFactory 或 Access denied for user。原因jdbc.properties 里的数据库用户名或密码不对或者 MySQL 用户没有访问当前库的权限。解决先用命令行手动登录验证mysql -uroot -p USE triage_system; SELECT 1;如果命令行能通过说明配置问题如果命令行也失败就是 MySQL 用户权限问题执行授权语句然后把密码改成与代码一致。现象三MySQL 8 下项目启动报 Unknown time zone 或者 Connection reset by peer。原因MySQL 8 驱动要求明确时区而旧项目的连接 URL 没有配置 serverTimezone。解决把驱动换成 mysql-connector-java 8.x并在连接 URL 加 serverTimezoneAsia/Shanghai这样时间和本地保持一致也避免 Jackson 序列化时间时把日期偏到前一天。4.2 功能类分诊列表不显示新患者、叫号按钮无反应现象四在患者管理里添加患者成功切到分诊管理却看不到刚加的人。原因最常见的是查询 SQL 默认过滤了 status 0或者前端默认只显示“未分诊”状态以及刚保存的数据还没生效。解决先到数据库里直接确认这条记录是否存在SELECT id, name, status, dept_id FROM triage_patient WHERE name 刚添加的患者名 ORDER BY id DESC LIMIT 3;如果记录存在就看前端列表是否按状态过滤如果记录不存在看后端有没有提交事务。SSM 项目里 Service 方法忘记加 Transactional 时插入报错后事务没回滚页面可能提示成功但数据库没写进去。这种情况我一般会在 Service 实现类上补上 Transactional(rollbackFor Exception.class)并打印 SQL 日志确认执行过程。现象五点击“叫号”按钮没反应浏览器控制台报 404 或 JS 错误。原因前端请求路径与后端 Controller 的 RequestMapping 不一致最常见是项目部署名导致上下文路径变化。解决打开浏览器开发者工具把报错的请求 URL 复制出来对比 Controller 里的路径。如果实际访问的路径多了一层 /triage_system而你 Controller 里写的是 /patient/call那前端应该写上下文路径加映射路径。用 Thymeleaf 或 JSP 的${pageContext.request.contextPath}获取上下文路径不要硬编码请求路径这是根本解决方式。4.3 数据类中文乱码、密码登录失败、日期显示偏移现象六添加患者后页面和数据库里的中文全是问号或乱码。原因连接串缺少 characterEncoding或者数据库表本身是 latin1 字符集。解决jdbc.urljdbc:mysql://localhost:3306/triage_system?useUnicodetruecharacterEncodingutf8useSSLfalse同时把表和字段字段类型都调整为 utf8mb4ALTER TABLE triage_patient DEFAULT CHARACTER SET utf8mb4; ALTER TABLE triage_patient MODIFY COLUMN name VARCHAR(50) CHARACTER SET utf8mb4 NOT NULL;调整之前注意备份数据这是最保险的做法。现象七输入正确密码却登录失败提示密码错误。原因用户表里的密码是加盐哈希后的结果而你手动改过表里的密码为明文或者你忘记了源码默认的初始化密码格式。解决进数据库查一下原用户密码字段确认它是否是一串长度固定的哈希值。如果是就不要手工 update 成明文应该走“修改密码”功能让后端用相同算法重新生成哈希。项目里如果有注册或重置密码入口从那里面操作是最稳妥的。现象八患者新增记录的时间显示比实际时间晚 8 小时。原因Tomcat 服务器时区和 MySQL 时区不一致数据库写入的 datetime 用的是系统时区前端展示时又按本地时区格式化导致偏移。解决统一时区。在连接 URL 后加 serverTimezoneAsia/Shanghai并在 MySQL 里执行 SET time_zone 8:00如果还是不对再看前端时间格式化的代码确认不是手动做了加减。这个问题经常被当成“玄学”其实就是时区没有统一排查时按数据库、JDBC 驱动、前端格式化三层逐一排除。5. 复现验证与进阶创建一个新科室把数据流从界面一路跟踪到数据库把系统跑通之后建议你做一次最小改造在科室管理里新增一个“发热门诊”用这一次操作验证整个 MVC 链路是否正确。这个验证方式能帮你检验前面所有配置是否真的生效也能让你快速看清一个 SSM 项目的可扩展性。新增科室页面的表单提交后后端 Controller 大致会做这样一件事Controller RequestMapping(/dept) public class DeptController { Resource private DeptService deptService; RequestMapping(/save) ResponseBody public JsonResult saveDept(Dept dept) { dept.setCreateTime(new Date()); dept.setStatus(1); deptService.insert(dept); return JsonMapper.toJsonResult(true, 科室添加成功); } }代码逻辑很简单但你可以跟着三步验证第一看数据库 triage_dept 表是否多出这条记录第二退出系统重新登录看分诊管理里患者选科室的下拉框是否出现“发热门诊”第三新建一个患者并把科室切换成发热门诊再完成一次叫号看列表里的状态是否从待分诊推进到叫号状态。做完这个实验你基本就掌握了这套源码的骨架一个实体对应一张表一个 Controller 对应一组页面操作状态字段贯穿业务链路。之后想加“医生排班”或“挂号统计”模块也是按同样的节奏去扩展建表、写实体和 Mapper、写 Service、写 Controller、挂菜单权限。另外我建议你花十分钟做一件事把 triage_patient 和 sys_user 的关联逻辑梳理一遍看看分诊记录里是否记录了操作医生 ID。如果有说明系统已经具备“统计每个医生接诊量”的基础如果没有这就是一个很好的扩展练习点。我在接手这类源码时通常会用 Navicat 或 DataGrip 把表之间的关系画出来再对照前端菜单确认每个菜单最终操作的是哪几张表这样做比凭空看代码高效得多。这套系统最让我认可的一点是它没有把业务做成玩具状态流转、权限控制、科室管理都是真实的实现方式。但我第一次跑起来时还是栽在端口占用和 MySQL 版本上后来我拿到任何 SSM 项目都会强制自己按“先看 SQL 脚本、再查 jdbc 配置、最后启动容器”的顺序走一遍确认环境三件套无误后再去动业务代码。希望这些经验帮你在跑这个分诊系统时少踩一些坑。本文还有配套的精品资源点击获取
阅读完成 · 觉得有帮助?