资讯详情

Java Spring Boot医院管理系统HIS源码部署与二次开发实战

📅 2026/10/7 3:27:29 | 华诺云谱 👁 阅读
Java Spring Boot医院管理系统HIS源码部署与二次开发实战
简介面向Java开发者和医院信息化学习者这份医院管理系统HIS源码包基于SpringBootShirolayuiThymeleaf构建涵盖门诊、住院、系统、统计、排班、仓库、药房等核心模块尤其侧重门诊与住院流程管理可用于毕业设计、课程实训或二次开发参考。压缩包共2000个文件以JS、TS、Java、HTML、CSS、XML等源码与配置文件为主同时包含SQL脚本、Maven配置、项目文档及安装视频结构清晰便于快速导入运行。资源包约117MB已有7487人学习下载具有较高的参考热度。配套安装视频和文档降低了环境搭建门槛读者能获得从部署到业务功能拆解的完整思路对理解挂号、收费、病历填写、病房管理等典型HIS场景很有帮助。1. 一套 Java Spring Boot 的医院管理系统 HIS 源码到底值不值得啃医院管理系统也就是常说的 HISHospital Information System拿到一套 Java Spring Boot 的源码大多数人第一反应是“先跑起来看看”。但如果你不是信息科的人也不是做医疗外包的很容易卡在第一步MySQL 装好了、Redis 起不来、Lombok 报错、端口被占折腾一晚上连登录页都看不到。这类源码通常配套安装视频但视频只能带你走一遍流程解决不了你环境里的特殊情况。HIS 源码和其他 Spring Boot 项目最大的区别在于它不是一个 CRUD 示例而是业务强约束系统。挂号、收费、药房库存、住院结算这些模块之间是强关联的改一张表结构可能牵动五个 service。你需要先建立这个认知再去看代码。适合的人有三类做医疗信息化的实施工程师、Java 后端想转行业项目的开发者、以及医院信息科要二次开发的同事。2. Spring Boot 在 HIS 里的选型先看清工程结构再决定怎么改2.1 HIS 系统的典型架构单体优先别一上来就想微服务HIS 源码最常见的形态是单体应用Monolith不是微服务。一家二级医院或者专科门诊日门诊量几百到一千单体应用完全扛得住。Spring Boot 负责提供 REST 接口和页面渲染MyBatis或 JPA操作 MySQLRedis 存验证码和 Session前端有 JSP 页面也有 Vue 打包后放进 Spring Boot 的 static 目录的做法。拿到源码先看 pom.xml确定几个关键依赖dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency dependency groupIdorg.mybatis.spring.boot/groupId artifactIdmybatis-spring-boot-starter/artifactId version2.3.1/version /dependency dependency groupIdcom.alibaba/groupId artifactIddruid-spring-boot-starter/artifactId version1.2.8/version /dependency dependency groupIdredis.clients/groupId artifactIdjedis/artifactId /dependency这里能看到源码的技术取向。druid 连接池是阿里巴巴的在国产 HIS 源码里出现频率极高因为很多系统要求保留 SQL 审计日志。如果你看到 druid 的 filter 配置别删那是用来记录慢查询和访问权限的。选型的理由很简单单体便于二次开发和部署。医院信息科的人员流动大微服务拆得再漂亮人走了没人能维护就是灾难。单体代码只要业务模块拆分清楚新人上手周期可以压缩到一到两周。2.2 拿到源码先分清三层Controller、Service、Dao以及它们之间的边界Spring Boot 项目结构大同小异但 HIS 源码的包名通常是按业务模块分的而不是按技术层分的。宁可按 module 分包别按 controller/service/mapper 分。看到类似这种结构是比较理想的com.hospital.his ├── common // 公共类返回结果、异常处理、工具类 ├── system // 系统管理用户、角色、菜单、日志 ├── outpatient // 门诊模块挂号、医生站、收费 ├── pharmacy // 药房模块库存、发药、盘点 ├── inpatient // 住院模块入院、医嘱、结算 ├── statistics // 统计报表门诊量、收入、药品消耗 └── config // 配置类拦截器、跨域、redis按业务模块分包的好处是你改收费的时候只需要盯住 outpatient 和 inpatient 两个包不需要翻遍整个项目找“订单服务”。HIS 里的业务逻辑复杂尤其是费用计算和库存扣减如果按技术层分包改一个字段要同时改 controller/service/mapper 三个包里的十几处容易漏改。看代码的顺序也按这个路径走先看 common 里的返回结果封装再看 system 里的登录和权限拦截器然后是具体的业务模块。登录是第一个要跑通的入口搞清楚登录用的 Token 存在 MySQL 还是 Redis这决定了你部署的时候必须启动哪些中间件。2.3 前端是 JSP 还是前后端分离这决定了部署方式HIS 源码有两种常见形态。第一种是纯后端工程页面用 JSP部署的时候打成 war 包扔进 Tomcat或者 Spring Boot 内置 Tomcat 直接跑。第二种是后端工程加前端工程前端用 Vue 写打包后 dist 目录里的文件复制到 Spring Boot 的 static 目录下。这个我在项目里见得太多了前端 npm run build 之后复制完就算部署完成。这种方案对实施工程师最友好医院现场不一定有 node 环境所有东西都在一个 jar 里。关键判断点在这mvn clean package java -jar his-system.jar如果启动后访问 http://localhost:8080 直接出页面那前端已经打进包里了。如果访问出 JSON 或者 404说明前端是独立的你需要再把 dist 文件复制到 static 目录。这一步不需要懂前端多少但决定你部署流程的长度。2.4 跟 MyBatis 相关的常见误区XML 里到底哪里动了手脚HIS 源码里 MyBatis 的 XML 文件通常比 Java 代码多得多因为复杂的联表查询都写在 XML 里。一个门诊收费记录可能要关联患者表、医生排班表、收费项目表、支付记录表四张表写注解 SQL 会写得非常痛苦。你也经常会看到 resultMap 里做了自定义映射字段名和实体类属性名对不上是这里兜住的。如果遇到某个接口只查出一部分字段先去看 XML。常见的问题是数据库字段改名了实体类没同步XML 里还是旧字段名。select idselectPatientInfo resultTypecom.hospital.his.common.entity.Patient SELECT p.patient_id AS id, p.patient_name AS name, p.id_card AS idCard, p.phone AS phone, p.create_time AS createTime FROM HIS_PATIENT p WHERE p.patient_id #{patientId} /select参数说明AS 后面的别名必须和实体类属性名一致否则 MyBatis 映射不到。这是 HIS 源码里最容易出“查出来了但值是 null”的坑。遇到这种问题优先检查 resultType 和 resultMap不要急着在 Java 代码里找原因。3. 核心业务模块和数据库表结构先懂业务再碰代码3.1 挂号与门诊一张主表加状态流转别被“状态机”吓到HIS 的第一条数据流是挂号。患者到院挂号员选择科室、医生、号别产生一条挂号记录。这张表是后续所有业务的源头看病历、开检查、收费、发药都靠它串起来。表设计通常是这样的CREATE TABLE HIS_REGISTRATION ( ID BIGINT PRIMARY KEY AUTO_INCREMENT COMMENT 挂号流水号, PATIENT_ID BIGINT NOT NULL COMMENT 患者ID, DEPT_ID BIGINT NOT NULL COMMENT 科室ID, DOCTOR_ID BIGINT NOT NULL COMMENT 医生ID, REG_TYPE TINYINT COMMENT 号别1-普通 2-专家 3-急诊, REG_STATUS TINYINT DEFAULT 0 COMMENT 状态0-待就诊 1-就诊中 2-已完成 3-已退号, REG_FEE DECIMAL(10,2) COMMENT 挂号费, CREATE_TIME DATETIME DEFAULT CURRENT_TIMESTAMP, UPDATE_TIME DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP );大部分医院管理系统源码都是这种设计。REG_TYPE 和 REG_STATUS 都是数字字典不是在表里写死中文。新人喜欢问为什么不用枚举医院实施工程师需要掌握的一个重要原则是数据库里尽量存字典值中文名称留给字典表去翻译。这样报表统计的时候直接 count 状态位不需要做字符串匹配。注意 REG_FEE 用 DECIMAL不要用 FLOAT 或 DOUBLE。这是医疗系统里被反复强调的钱和金额精度问题涉及钱浮点数一旦出现精度误差对账就过不去。3.2 药房与处方库存扣减是事务重灾区门诊医生开完处方药房要按处方发药。这个流程涉及两张表处方明细表和药品库存表。典型场景是发药时扣库存如果刚好同一时刻两个窗口在发同一种药库存就可能在并发下出错。HIS 源码里处理这个问题的思路各不相同我见过比较靠谱的是用“乐观锁 事务重试”来兜底。UPDATE HIS_DRUG_STOCK SET STOCK_COUNT STOCK_COUNT - #{count} WHERE DRUG_ID #{drugId} AND STOCK_COUNT #{count}这个 SQL 的巧妙之处在于WHERE 里带上了 STOCK_COUNT #{count} 的条件满足才更新不满足就返回影响行数为 0。上层 service 拿到影响行数为 0 的时候要么抛异常要么提示库存不足。这种写法比 select 出来再 if 判断地“先查后改”要安全得多。实际改代码时我一般建议不要只在这里“锁行”还要保证事务范围覆盖“扣库存 写发药记录”两步让两条操作在同一个事务里Transactional(rollbackFor Exception.class) public void dispenseDrug(Long registrationId, ListPrescriptionItem items) { // 1. 写发药记录 // 2. 扣减库存每次扣减都检查影响行数 // 3. 如果影响行数为 0抛出运行时异常触发回滚 }参数说明rollbackFor Exception.class 很关键。Spring 的 Transactional 默认只在遇到 RuntimeException 时回滚如果业务代码抛的是 checked exception又没指定 rollbackFor事务就不会回滚库存和发药记录就产生了不一致。这是 HIS 二次开发里最常见的坑。3.3 住院与费用结算流水账式的追加设计住院这块和门诊不一样患者入院后不是按次付费而是每天产生各种费用床位费、诊疗费、检查费、药品费。设计上最核心的就是一张费用明细表所有费用都往这张表里追加记录结算的时候按时间段汇总。CREATE TABLE HIS_INPATIENT_FEE ( ID BIGINT PRIMARY KEY AUTO_INCREMENT, INPATIENT_ID BIGINT NOT NULL COMMENT 住院号, FEE_TYPE VARCHAR(20) COMMENT 费用类型BED-床位 DRUG-药品 CHECK-检查 TREAT-治疗, FEE_AMOUNT DECIMAL(10,2), -- 发生金额 FEE_TIME DATETIME DEFAULT CURRENT_TIMESTAMP, -- 费用发生时间 IS_SETTLED TINYINT DEFAULT 0 COMMENT 是否已结算0-否 1-是 );append-only 的设计好处在于任何时间点都能根据费用明细重算患者的欠费情况。出院结算时直接 sum 出来“应收总额”再减去“已预交金”就知道患者还差多少钱。这套逻辑任何一家医院的 HIS 都是按这个模型跑的。结算的过程才复杂。跨医保、商保、自费混合支付的时候金额分摊要算得非常仔细。做二次开发时别去改费用明细表里已经封账的历史数据这是红线。哪怕因为某种原因多收了也要靠“冲正记录”的方式来做负数费用冲销。3.4 字典管理为什么 HIS 里的“类型”都是用 ID 而不是字符串HIS 源码里十张表有九张都带 TYPE 或 STATUS 字段这些值基本都在统一字典表里。医院管理系统的字典设计通常是一个字典大类表 一个字典明细表大致像下面这样CREATE TABLE SYS_DICT_TYPE ( ID BIGINT PRIMARY KEY, DICT_CODE VARCHAR(30), DICT_NAME VARCHAR(60) ); CREATE TABLE SYS_DICT_ITEM ( ID BIGINT PRIMARY KEY, DICT_TYPE_ID BIGINT, ITEM_CODE VARCHAR(30), ITEM_NAME VARCHAR(60), SORT_NO INT );我做项目的习惯是所有下拉框和数据列表都从字典表读这样改名称、加选项都不动代码。但要注意字典表修改会直接影响前端展示医院的“科室名称”如果改错了历史数据的报表统计就乱了所以字典表的操作都必须记录操作日志。很多源码里也做了这个逻辑在字典管理页面就能看到“操作人、操作时间、修改前后值”的记录这个功能轻易不要动。4. 把 HIS 源码从零跑通JDK、Maven、MySQL、Redis 一次到位4.1 环境准备先核对版本再动手安装HIS 源码的 Java 版本分布比较杂老项目常见 JDK 8新源码有 Spring Boot 2.7 配 JDK 8 的也有 JDK 11 的。不同版本之间差别主要是 javax 和 jakarta 的包名——这个区别是很多部署问题的根源。拿到源码先执行java -version mvn -version看 pom.xml 再确认parent groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-parent/artifactId version2.5.12/version /parentSpring Boot 2.x 用 JDK 8 或 JDK 11 都行但不要用 JDK 17 硬跑javax 包名会出问题被编译报错淹到怀疑人生。有 Jenkins 的时候怎么规避呢建议在 pom.xml 里强制编译版本properties java.version1.8/java.version maven.compiler.source1.8/maven.compiler.source maven.compiler.target1.8/maven.compiler.target /properties如果你的机器上装了多个 JDK 版本记得用 JAVA_HOME 指定。部署 MySQL 时HIS 源码对 MySQL 5.7 和 8.0 的兼容性有差异主要在于驱动 jar 依赖。4.2 创建数据库并导入初始 SQL 数据拿到源码包后搜一下 SQL 脚本文件一般是 schema.sql 或 his_db.sql。MySQL 里先建库再执行CREATE DATABASE his_db DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; USE his_db; SOURCE /path/to/his_db.sql;导入之后不要急着启动先看三张表的数据量sys_user管理员账号、sys_menu菜单权限、his_registration是否有测试数据。这套源码能不能登录就看 sys_user 表里有没有初始账号密码。有些源码的初始密码写在 README 里有些写在 SQL 里比如 MD5 加密后的 “123456”。在 8.0 的 MySQL 里导入 HIS 脚本时注意 SQL 里不能出现忽略大小写的表名参数。如果脚本里写了 ENGINEInnoDB导入慢通常是因为索引和约束多耐心等一下。4.3 修改 application.yml数据库连接、Redis、文件上传路径打开 src/main/resources/application.yml这是把源码跑起来的关键地方大多数运行环境问题都出在这里server: port: 8080 spring: datasource: url: jdbc:mysql://localhost:3306/his_db?useUnicodetruecharacterEncodingutf-8useSSLfalseserverTimezoneAsia/Shanghai username: root password: 123456 driver-class-name: com.mysql.cj.jdbc.Driver redis: host: localhost port: 6379 database: 0 password: 123456 mybatis: mapper-locations: classpath:mapper/*.xml configuration: map-underscore-to-camel-case: true file: upload-path: D:/his-upload/参数说明useSSLfalse 一定要保留尤其 MySQL 8.0 在高版本 JDBC 驱动下默认开启 SSL医院局域网环境未必支持连不上时大多是这个问题。serverTimezone 必须设置否则日期字段的读取会差 8 个小时。Redis 如果没设密码password 注释掉千万别留个空字符串某些客户端会解析报错。un-下划线到驼峰命名必须打开HIS 表的字段都用下划线命名实体类都是驼峰这一步不开启查询结果全是 null。4.4 Maven 打包与 jar 启动按顺序执行mvn clean package -DskipTests如果 Maven 下载依赖卡住考虑两个原因用 mvn -v 确认没有走到错误仓库镜像仓库 config 推荐用阿里云镜像可以在 settings.xml 里替换。打包完成之后jar 在 target 目录。启动时先确认 Redis 和 MySQL 都已经被你的服务连接再执行java -jar target/his-0.0.1-SNAPSHOT.jar --server.port8080看到 Started Application 日志然后浏览器访问http://localhost:8080/login如果看到验证码图片、页面样式正常说明静态资源映射没问题。如果验证码转圈或加载失败优先排查 Redis 连接。4.5 用安装视频的节奏来验收登录、患者建档、挂号一条龙拿到带安装视频的 HIS 源码我的习惯是按视频先过一遍但不直接照抄。视频可能是用 Windows 录的路径、数据库版本和你本机对不上是很正常的事。你真正要验收的是三个核心场景能走通这套就算部署完成第一系统管理员登录能进到用户管理页面说明鉴权、菜单加载、动态路由都没问题。第二从患者建档开始新建一个患者然后挂号能完成这个流程说明数据库的增删改查正常流转。第三开一张处方并完成收费说明最核心的金额计算和状态更新链路是通的。5. 部署 HIS 源码的踩坑记录从编译到上线最常见的 5 个问题5.1 数据库连不上同一个日志三个不同原因现象启动 Spring Boot 项目时报Access denied for user或Communications link failure。原因一密码错误这个好排查。原因二MySQL 8.0 的加密方式跟 MySQL 5.7 不同驱动版本太低会直接拒绝连接换成com.mysql.cj.jdbc.Driver并升级 mysql-connector-java 到 8.0.x。原因三useSSLtrue导致 SSL 握手失败在局域网环境尤其常见。解决把 datasource 的 url 调成上面那套参数优先复制不要自己缩。真正的坑是改了一半漏了serverTimezone导致启动成功但所有日期字段查询差 8 小时。这是最容易翻车的地方。5.2 启动后登录页能打开但点击登录就报错Redis 连接被拒现象页面能加载说明前端资源正常但输入用户名密码后提示“验证码错误”或 “Redis 连接异常”。原因HIS 的验证码存放在 RedisRedis 没起来或者密码不对验证码就永远校验不过。很多 HIS 源码把验证码的逻辑做到了RedisConfig里不是微信验证码而是一个普通图形验证码。解决检查 Redis 进程是不是真的活着执行redis-cli ping。如果返回 PONG说明服务在再看 application.yml 里 host、port、database 是否对得上。5.3 IDEA 导入源码后一片红Lombok 插件与 JDK 版本现象导入项目后很多实体类标注 Data然后代码里 getter/setter 全是红色报错编译也过不了。原因这种 HIS 源码大量使用 Lombok。IDEA 如果没装 Lombok 插件或者没开启 annotation processing代码就全是红色。JDK 版本过高也容易在编译阶段报错。解决IDEA 插件市场搜 Lombok 安装重启后在 Settings - Build - Compiler - Annotation Processors 里勾选Enable annotation processing。把 Project SDK 切到 JDK 8 或 11。5.4 文件上传图片路径能写不能读Tomcat 虚拟路径映射现象上传患者头像或报告图片后文件确实写到本地磁盘了但页面访问时图片 404。原因源码里通常有一个配置类实现WebMvcConfigurer做资源映射。常见写法是这样的Configuration public class FileConfig implements WebMvcConfigurer { Value(${file.upload-path}) private String uploadPath; Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler(/upload/**) .addResourceLocations(file: uploadPath); } }启动后访问http://localhost:8080/upload/xxx.jpg404多半是 upload-path 最后没带斜杠或者相对路径不对。解决配置绝对路径并且保证路径尾部有分隔符Tomcat 的 file: 映射要求这一点。这是 Windows 上最容易翻车的地方。5.5 数据库导入时报错SQL 脚本版本与字符集现象用 Dinner Source 导入某份 HIS 的 SQL 脚本到一半报Unknown collation: utf8mb4_0900_ai_ci直接中断。原因这个排序规则是 MySQL 8.0 默认的如果导入到 MySQL 5.7 就会报错。解决把脚本开头的utf8mb4_0900_ai_ci全局替换成utf8mb4_general_ci再执行一次。如果脚本开头是SET FOREIGN_KEY_CHECKS 0导入完记得手动恢复否则后续删除数据会因外键约束报莫名其妙的错。6. 把 HIS 源码改造成能上线的样子三项必须做的验证6.1 用 SQL 验证门诊主流程的数据闭环跑通登录只是开始。真正上线前我会先拿 SQL 把门诊主流程验一遍确认核心数据闭环是通的-- 1. 统计某一天的门诊挂号量 SELECT COUNT(*) FROM his_registration WHERE DATE(create_time) CURDATE(); -- 2. 统计收费总额验证应收、实收、退费数据一致 SELECT SUM(fee_amount) FROM his_outpatient_fee WHERE settle_status 1 AND create_time BETWEEN ? AND ?; -- 3. 验证药品库存和发药数量之间的约束 SELECT d.drug_name, d.stock_count, SUM(o.drug_count) AS 已发数量 FROM his_drug_stock d LEFT JOIN his_prescription_detail o ON d.drug_id o.drug_id GROUP BY d.drug_id;这三个 SQL 查不到数据不代表系统有问题但查出来的数据对不上就说明事务或状态流转写得不严谨。线上验收时先跑这三个查询是最快的体检方式。6.2 事务注解别只待在 Service 层跨表操作必须显式声明见过很多 HIS 源码的 Service 里方法直接public void addFee(...)不加Transactional遇到一次异常时费用明细写进去了但库存没扣或者收费状态没更新。这种隐患非常隐蔽——因为单个操作看着没错只有并发或异常时才会冒出来。按照医院这种强资金场景事务注解的粒度应该落到“一次完整业务”上挂号事务、收费事务、退费事务、发药退药事务。你在这类源码上做二次开发时碰到的方法是跨表写操作先问一句如果这里出异常前面的写操作能不能回滚如果答案不确定就给方法加上Transactional(rollbackFor Exception.class)。这是改 HIS 代码的基本素养与其说是技巧不如说是底线。6.3 权限模型和密码安全HIS 的默认钥匙必须换很多 HIS 源码的管理员初始账号密码是 admin/admin123 或者类似明文或弱哈希。上线前第一件事是把默认密码改掉并确认用户的密码存储方式是加盐哈希而不是原生 MD5。看代码时找密码校验那一行// 常见的安全校验方式BCrypt if (passwordEncoder.matches(rawPassword, user.getPassword())) { // 登录成功 }如果源码里是这种写法说明安全设计是成熟的。碰到MD5 明文拼接的旧方案时尽量改造一下。医疗数据是敏感数据医院对安全的看重程度比你想象中的要高。上线前还要做一遍越权检查普通医生账号能不能访问管理员接口接口路径里带/admin、/system的确认权限拦截器都覆盖到了。很多“源码跑通了”的团队恰恰是没做这一步上线后被检查出问题才补代价就大了。结个尾这段时间经手 HIS 源码下来的教训是跑通不难改好很难。不要迷信“拿到源码就是拿到系统”报表对不上账、库存并发扣错、权限控制漏了这些才是让医院炸锅的事。先把环境和主流程摸透再动任何一行代码这是我给所有接此类项目的人的建议希望帮到你。本文还有配套的精品资源点击获取
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。

↑