简介基于Java语言采用SpringBoot框架、Layui界面框架与Shiro权限框架开发的医院管理系统HIS源码同时配套小程序端和安装教程适合医疗信息化方向的学生、开发者以及进行毕业设计或项目二次开发的人群。系统数据库共三十六张表业务覆盖门诊、住院、系统管理、统计管理、数据中心、排班管理、仓库管理和药房管理八大模块其中门诊管理包含用户挂号、处方划价、项目划价、项目缴费、项目检查、药品缴费、门诊患者库住院管理包含入院登记、缴费管理、药品记账、项目记账、出院结算系统管理提供菜单、角色、用户、图标和数据源监控。挂号时会校验患者姓名、年龄、手机号、身份证号等资料可识别是否正在就诊存在未完成项目时需结清费用后方可转入住院业务规则较为完整。压缩包内共有三万八千一百七十一个文件整体大小约一百九十九MB主要包含后端源码、前后端脚本、小程序页面与样式文件、数据库脚本、说明文档及配置文件便于导入工程与查阅模块。目前已有1043人学习下载配套视频与业务参考文档存放于云盘结合安装教程可快速搭建环境源码模块划分清晰适合深入分析挂号校验、费用结算、药品库存联动等逻辑也可作为中小型医院信息管理系统的参考模板。1. 拿到带小程序的Java医院管理系统HIS源码先别急着启动这套带小程序的Java医院管理系统HIS源码最常见的交付形态是“后端Spring Boot工程 医护/管理后台 患者微信小程序端”三个部分捆在一起。很多人在下载后第一步就双击启动后端结果被数据库初始化、Redis连接、小程序AppID替换这些前置条件卡住误以为是源码有问题。我一般会建议先花半小时把源码里某个模块的表结构、application配置和前端目录认完再谈启动。这套东西真正适合的人是两类要交付医院信息化项目的实施与开发人员以及想用真实业务做Java全栈练习的进阶学习者。它能帮你把挂号、收费、药房、病历这些HIS核心流程完整跑起来但代价是环境依赖比普通练手项目多得多。2. 拆开源码看HIS的技术栈和我选型的理由2.1 为什么医院管理系统还坚持用单体架构HIS源码虽然叫系统但绝大多数交付版本仍是单体应用而不是Spring Cloud微服务。原因不复杂医院内网部署、使用人数有限、业务模块之间强耦合单体反而最容易维护。常见的做法是Spring Boot做后端配合MyBatis Plus操作MySQLRedis负责缓存和验证码这类短时效数据前端管理端用Vue或Thymeleaf患者端是微信小程序。选Spring Boot而不是Spring MVC老工程是因为内置Tomcat、自动配置和约定大于配置能大幅减少安装教程里的手工步骤。不要指望这套源码里包含完整的微服务体系。我的判断标准是看它有没有独立的注册中心和网关模块。如果只有业务模块加一个启动类那就按单体处理。单体HIS的优势在部署时体现出来一台4核8G的服务器就能同时跑后端和MySQL患者小程序和院内管理端共用同一套API出现问题时排查链路也短。对中小医院和诊所场景来说这个边界刚刚好。2.2 从入口到药房后端MVC三层的源码阅读顺序拿到源码后先看目录结构这是最可靠的一步。常见工程会按业务模块分包比如doctor、registration、pharmacy、outpatient而不是把所有Controller堆在一起。我的阅读顺序是启动类到application.yml再到一个小模块的Controller、Service、Mapper三层最后看SQL脚本。!-- pom.xml 中决定运行方式的关键依赖 -- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency dependency groupIdcom.baomidou/groupId artifactIdmybatis-plus-boot-starter/artifactId version3.5.x/version /dependency dependency groupIdmysql/groupId artifactIdmysql-connector-java/artifactId scoperuntime/scope /dependency这段依赖说明三件事web起步依赖决定了它是以HTTP接口方式对外服务MyBatis Plus决定了SQL操作大部分靠Mapper接口和Wrapper完成MySQL驱动说明数据库是MySQL而不是Oracle。注意MyBatis Plus版本在3.5.x之后分页插件写法有变化如果源码里用的是旧版分页写法启动后访问列表接口翻页报错时优先排查插件版本匹配。Service层是HIS业务的核心不要只看Controller。比如挂号的真正逻辑不在Controller里而在Service中对号源剩余数、患者档案、费用记录这三张表的联合处理。顺着一个最小业务闭环去读源码比按文件列表扫一遍高效得多。2.3 小程序端用uni-app还是原生先看交付场景带小程序的HIS源码里患者端通常负责预约挂号、门诊缴费、报告查询这几个轻量场景。技术实现上两种最常见原生微信小程序或者uni-app跨端工程。判断依据很简单——看根目录是project.config.json还是manifest.json。前者是原生后者是uni-app。如果是原生小程序直接用微信开发者工具导入即可页面文件是wxml和wxss如果是uni-app源码是vue文件必须经过HBuilderX或命令行编译成小程序产物才能导入。很多人拿到uni-app版本后直接拿开发者工具打开src目录结果页面空白这就是因为没走编译这一步。我在实际交付中更倾向原生小程序原因不太技术但很现实医院信息科人员后续改动时原生工程的排查路径最短不需要理解打包链。3. 安装教程落地环境搭建、数据库初始化和参数配置3.1 先把JDK、MySQL、Redis装齐含Docker快速方案按照安装教程把环境一次装对可以避免后边一半以上的报错。JDK建议用1.8或11MySQL用5.7或8.0Redis必须装但本地不要求密码。新手最容易翻车的地方是JDK配了但JAVA_HOME没生效或者MySQL初始化完忘记密码导致后面怎么连都失败。以下是一套我常用的快速环境准备命令按顺序执行即可。# 以 Ubuntu/Debian 为例安装基础环境 sudo apt update sudo apt install -y openjdk-11-jdk mysql-server redis-server maven # 把当前用户加入 mysql 管理组并启动服务 sudo service mysql start sudo service redis-server start # 检查版本确保三条命令都有输出 java -version mysql --version redis-cli ping每一条命令都不白执行。新增openjdk-11-jdk是为了满足Spring Boot 2.x对Java 11的兼容mysql-server提供建模和业务数据存储redis-server支撑验证码和token缓存。redis-cli ping返回PONG是Redis可用的最直接证据。Maven单独安装是因为后端工程通常依赖私有仓库和复杂依赖树没有Maven就没法解析pom.xml里的全部jar包。如果你已经在用Windows环境我建议别在环境上较劲。常见的做法是装一个VMware虚拟机在虚拟机里跑Linux环境数据库和后端都放在虚拟机内本机只跑微信开发者工具。这样做的好处是避免MySQL在Windows上因服务名和端口占用导致的一系列奇怪问题也方便随时快照回滚——安装失败时这就是你的后悔药。3.2 数据库脚本的导入顺序与字符集选择数据库是HIS源码里最容易出问题的地方。源码的sql目录下通常有多个脚本常见的有init.sql、data.sql、quartz.sql等。这些脚本之间存在顺序依赖比如先建表才能插数据先建基础数据才能算费用。不看脚本直接全选执行的话会出现外键冲突或重复建表的报错。最稳妥的做法是打开脚本确认文件内是否有CREATE DATABASE语句再决定用哪种方式导入。# 登录MySQL后先建库再按顺序导入脚本 mysql -u root -p CREATE DATABASE his_db DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; USE his_db; SOURCE /path/to/sql/init.sql; SOURCE /path/to/sql/data.sql;这段命令的关键是字符集指定。HIS里大量存在患者姓名、药品名称、费用备注这些中文数据utf8mb4才能完整支持四字节字符和中文排序。如果建库时省略字符集系统默认可能是latin1或utf8mb3启动后页面所有中文变问号这类问题改代码没用只能重建库重导数据。导入脚本后建议立即执行SHOW TABLES;确认核心表齐全像patient_info、registration_order、prescription这些关键表要一眼能看到。3.3 必改的application.yml参数数据源、Redis与文件上传后端配置集中在application.yml或application.properties里。我打开这个文件的第一件事就是找spring.datasource和spring.redis两段。安装教程里给的可能只是示例值真正的数据库密码和Redis地址必须按你的实际环境改。另一个容易被忽略的是文件上传路径HIS里涉及报告、影像附件的保存位置如果路径不存在启动不报错但上传接口会一直失败。spring: datasource: url: jdbc:mysql://localhost:3306/his_db?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/Shanghai username: root password: your_password driver-class-name: com.mysql.cj.jdbc.Driver redis: host: localhost port: 6379 database: 0 mybatis-plus: configuration: map-underscore-to-camel-case: true global-config: db-config: logic-delete-field: deletedurl里的serverTimezoneAsia/Shanghai几乎必填不填的话MySQL 8驱动默认按UTC取时区导致所有时间字段比北京时间慢八小时挂号时间的记录会错位。map-underscore-to-camel-case这个选项决定数据库的patient_id能不能自动映射到Java的patientId关掉之后MyBatis Plus查出来的对象全是null这是新手最常遭遇的黑匣子问题。logic-delete-field是逻辑删除字段如果你发现删除数据后列表里记录还在多半是这个字段与实体里的TableLogic没对上。3.4 MyBatis Plus生成SQL/代码的参数边界很多HIS源码会附带一个代码生成器模块它可以把数据库表反向生成实体类、Mapper接口和ServiceImpl这正是MyBatis Plus“根据实体类生成创建表SQL语句”的逆向能力。但生成器不是无脑用的使用时必须控制扫描的表名范围。默认配置会扫描整个数据库把quartz任务表、flyway版本表也生成一遍污染工程目录。// 代码生成器的关键配置按需生成指定业务表 String[] tables {patient_info, registration_order, prescription_detail}; GeneratorConfig config new GeneratorConfig(); config.setTables(tables); config.setPackageName(com.hospital); config.setEntitySuffix(Entity); config.setMapperSuffix(Mapper);这段配置把生成范围限制在三张业务表上避免把系统表也卷进来。包名设置会影响生成的目录层级一旦确定后不要随意改否则spring扫描不到Mapper导致启动报Invalid bound statement错误。生成完成后要人工核对的是实体类里的日期字段类型数据库datetime类型默认生成LocalDateTime如果你的代码里还在用java.util.Date序列化和比较会出现类型匹配异常。4. 后端启动到小程序联调复现整套系统的关键路径4.1 后端启动的最小命令和启动成功的判断标准环境就绪后启动后端最可靠的方式是Maven直接起不用先打包。在工程根目录执行mvn spring-boot:run它会先解析依赖再启动应用日志输出比IDE的Run窗口更完整。如果你已经打好jar包用java -jar target/his.jar也一样。关键是要知道什么叫启动成功——不是看到Spring的Logo就算成功要判断嵌入式Tomcat端口和DispatcherServlet是否就绪。# 开发阶段推荐的方式观察启动日志 mvn spring-boot:run # 生产模拟方式后台运行并记录日志 nohup java -jar his.jar --spring.profiles.activeprod his.log 21 第一种方式适合本地调试CtrlC可以干净停掉。第二种方式适合部署到服务器做演示它把标准输出和错误输出都重定向到日志文件。用--spring.profiles.activeprod指定生产配置前提是application-prod.yml存在且里面的数据源指向真实数据库。启动日志里看到Started Application in x.xxx seconds说明启动完成看到Tomcat started on port(s): 8080说明接口地址确定。如果一直卡在Initializing Spring DispatcherServlet通常是Mapper扫描路径错了去启动类检查MapperScan注解的包路径是否和Mapper接口实际路径一致。4.2 用微信开发者工具导入小程序工程并解决域名校验小程序端的联调第一步是让代码跑起来。原生小程序直接从微信开发者工具导入工程目录uni-app工程要先用HBuilderX发行或CLI方式编译到dist/build/mp-weixin再导入该产物目录。导入后最常遇到的第一个坑是AppID不合法或未配置。你有两个选择申请一个测试号或者使用开发者工具提供的测试号AppID。测试号能跑通大部分功能但获取手机号这种能力必须用已认证的AppID。// project.config.json 中需要确认的编译配置 { appid: 你的小程序AppID, compileType: miniprogram, libVersion: 3.4.0, setting: { urlCheck: false } }urlCheck这个字段非常关键。它控制小程序是否校验request域名必须是HTTPS且已在公众平台备案。本地联调时后端是http://localhost:8080如果不把urlCheck关掉所有请求都会报“url not in domain list”。开发者工具中也有对应开关勾选“不校验合法域名、web-view业务域名、TLS版本以及HTTPS证书”即可。但要注意这只是本地调试手段真机预览或正式发布时后端必须使用HTTPS域名否则在手机上无法访问。4.3 微信登录code2Session与获取手机号的实际流程HIS里患者预约挂号和查询报告都需要绑定真实身份手机号是重要信息。微信小程序获取手机号的常规路径是前端用wx.login拿到临时code后端拿code和AppSecret去微信接口换openid和session_key再结合前端getPhoneNumber触发的授权事件完成手机号绑定。注意从2023年后手机号快速验证组件改为收费接口部分源码仍保留旧版getPhoneNumber回调联调时要看后端有没有申请对应的接口权限。// 小程序端登录请求封装先登录拿code再换取业务token wx.login({ success: (res) { wx.request({ url: http://localhost:8080/api/auth/login, method: POST, data: { code: res.code }, success: (resp) { const token resp.data.data.token; wx.setStorageSync(token, token); } }); } });这段代码实现了无感登录的第一步。code是五分钟内有效的临时凭证不能复用。后端拿到code后调用微信的jscode2session接口得到openid和session_key然后生成你自己的业务token返回给前端。后续所有需要登录态的接口请求头里都要带上这个token。如果登录接口返回40029错误说明code无效常见原因是局域网后端获取不到微信接口时超时重试而不是代码逻辑问题。4.4 联调利器开发者工具抓包和导航栏高度适配小程序联调时最大痛点是没有浏览器那样的Network面板直观很多请求失败只在小程序控制台输出一行报错。此时用抓包工具看HTTP请求和响应是最靠谱的。Charles是常见选择也可以先用微信开发者工具自带的面板。抓包观察接口返回时重点关注HTTP状态码、后端返回的JSON结构里code字段和message字段。HIS源码的返回值通常是{code: 200, data: {...}, message: success}这样的统一结构如果code是500问题不在前端而在后端日志抛出的异常。/* 适配小程序顶部导航栏高度的通用做法 */ .page { padding-top: calc(var(--status-bar-height) 44px); box-sizing: border-box; }这段样式解决的是页面内容被胶囊按钮挡住的问题。自定义导航栏时不同机型状态栏高度不同var(--status-bar-height)由小程序环境自动注入44px是默认导航栏高度。如果你发现真机上页面顶部被遮住最直接的办法不是改这个值而是让后端返回界面直接使用默认导航栏省去手动适配的麻烦。这套HIS里患者端页面不复杂用默认导航栏最稳。5. 本地联调避坑与常见问题排查5.1 MySQL 8时区导致的时间差八小时现象挂号记录的时间和实际北京时间差了整整八小时医生端看到的预约时间全部延后。原因MySQL 8的驱动默认时区是UTC数据库连接串里没有指定serverTimezoneSpring Boot读取时按UTC转换输出时又按本地时区展示来回一算就偏了八小时。解决在数据源url最后加上serverTimezoneAsia/Shanghai并建议同时修改MySQL全局时区。修复后必须重启后端应用而不是只刷新页面因为连接池里的旧连接不会自动应用新配置。这个坑在登录日志里几乎没有明显报错只有对比数据库原始时间才能发现。5.2 主键Long传到小程序变成科学计数法现象患者ID是9223372036854775807这样的大数小程序页面上显示成9.223372036854776e18点击详情时ID变成9223372036854776000请求直接查不到数据。原因Java的Long类型是64位而微信小程序的JavaScript Number是双精度浮点超过2的53次方后精度丢失。ID本身被错误地舍入后端收到的参数已经不是真正的患者ID。解决不要在JSON序列化时输出原始Long值。常见做法是给Spring Boot全局Jackson配置增加Long转String的序列化器或者修改实体类中ID字段的JsonSerialize注解为ToStringSerializer。HIS源码里那些最关键的主键和业务编号字段容易出现这个问题修改后需要重新生成或手动改实体类。5.3 局域网真机调试能用换台电脑不通现象自己电脑上后端、小程序都正常拿到医院演示的笔记本上用真机预览所有请求失败但开发者工具里又是通的。原因我用localhost作为API地址后端起在自己电脑上真机访问的localhost指向的是手机自身自然连不到电脑的服务。开发者工具有时默认帮你做了代理真机没有这套代理逻辑。解决把接口地址改成电脑的局域网IP比如http://192.168.1.100:8080同时确认Windows防火墙放行了8080端口。手机和电脑要在同一网段公司网络开启了AP隔离的话手机和电脑虽然都连着同一个WiFi但互相访问不了此时得换热点测试。5.4 金额字段别用double药品单价计算差一分钱现象开处方时药品单价0.1元数量3应收0.3元但收费列表显示0.30000000000000004对账时总对不上。原因Java的double和float是二进制浮点数无法精确表示十进制小数。HIS源码里只要涉及金额的字段或局部变量用了double计算到小数位较多时会积累误差。解决数据库金额字段用decimal(10,2)Java实体用BigDecimal所有费用计算统一用BigDecimal的add和multiply方法禁止直接乘double。这一步最好在拿到源码后全局搜索private double和private float排查计价和收费模块是否混入浮点类型。6. 上线前的验证清单和我的备份习惯6.1 验证挂号、收费两条主链路的最少路测HIS系统上线前不需要把每个功能点都测完但两条核心链路必须跑通。第一条是患者端挂号链路小程序登录、选择科室号源、提交挂号、支付成功、医生端能看到号。第二条是收费链路医生开处方、收费员结算、药房看到待发药列表、库存扣减。如果这两条链路能连贯走完说明基础表关系和核心事务是可靠的。我用一个只有两条记录的小本子记录每次测试的患者姓名和操作时间避免用真实患者数据反复测试造成重复挂号和垃圾号源。上线当天第一次真实挂号时我会盯着后端日志里的SQL输出和接口耗时。正常情况下挂号接口应该在200毫秒内完成如果超过三秒大概率是号源表缺少索引而不是代码逻辑问题。6.2 用mysqldump做定时备份的一个实用写法数据库备份是HIS系统最不能省的运维操作。我习惯每天凌晨做一次全量备份保留最近7天这个节奏对中小医院足够。以下脚本同时备份数据结构和存储过程mysqldump非常老派但可靠比在应用层做导出更可信。#!/bin/bash BACKUP_DIR/data/backup/his DATE$(date %Y%m%d) mysqldump -u root -pyour_password \ --single-transaction --routines --triggers \ his_db | gzip ${BACKUP_DIR}/his_${DATE}.sql.gz find ${BACKUP_DIR} -name his_*.sql.gz -mtime 7 -delete--single-transaction保证备份过程中不锁表院内用户白天也能正常挂号收费。--routines和--triggers会连同存储过程、触发器一起备份否则恢复后自定义统计函数全丢。最后一行用find清理七天前的旧文件避免脚本长期运行把磁盘写满。第一次跑完这个脚本后我会手动执行一次gzip -t验证备份文件完整性而不是等到事故当天才发现备份是坏的。这套Java医院管理系统HIS源码的交付价值不在于代码多炫而在于它把挂号、收费、药房、患者端小程序串成了一条完整的业务闭环。我接手这类项目时有个固定习惯先搭环境再改配置先跑通再优化每一步都不跳过日志观察。遇到问题时别第一时间怀疑源码残缺多半是环境参数和版本匹配没对齐。希望这个方向的经验能帮到你少走我当年走过的弯路。本文还有配套的精品资源点击获取