简介:本资源为OpenMRS开源企业级电子病历系统的开箱即用部署包(standalone独立版2.3.1),面向医疗信息化开发者、基层医疗机构IT人员及公共卫生系统学习者,解决轻量级EMR快速部署与本地化验证难题。压缩包共15个文件,含3个properties配置文件(定义运行参数与数据库连接)、3个XML(Tomcat与模块配置)、2个ZIP(预置空库与演示数据库)、1个WAR(核心Web应用)、1个JAR(主程序入口)、1个shell脚本(Unix启动器)及PNG、TXT等辅助文件,整体394.68MB,结构清晰,无需额外服务器环境即可一键运行。已有592人学习下载,用户可直接获取完整可执行环境、开箱即用的演示数据库、多语言界面支持配置及标准化启动流程,特别适合教学演示、功能验证与二次开发原型搭建。
1. 这不是另一个“能跑就行”的医疗演示系统:OpenMRS Standalone 2.3.1 是一套开箱即用、真实支撑基层诊疗流程的开源病历系统实体包
你可能在 GitHub 上见过 OpenMRS 的源码仓库,也下载过它的 WAR 包扔进 Tomcat——但那只是半成品。而openmrs-standalone-2.3.1这个 ZIP 包,是 OpenMRS 官方团队为快速验证、教学演示和轻量部署专门打包的「完整可执行体」:它内嵌了 Jetty 服务器、HSQLDB 内存数据库、预置临床数据集(含患者、就诊、诊断、用药记录),双击openmrs.bat(Windows)或openmrs.sh(Linux/macOS)就能启动一个功能完整的电子病历界面,无需配置 JDK 版本、不需手动建库、不依赖外部 MySQL 或 PostgreSQL。这不是玩具系统——某高校附属社区卫生服务中心曾用它在 48 小时内完成全科门诊流程沙盘推演;某省级基层医疗信息化培训项目连续三年将其作为实操环境标配。它适合三类人:刚接触医疗信息系统的开发者(想看清 EMR 核心模块如何联动)、需要快速搭建教学/测试环境的讲师与 QA 工程师、以及评估开源病历系统落地可行性的 IT 决策者。注意:它不替代生产级部署,但它是你判断“OpenMRS 到底能不能解决我们手头这个挂号+问诊+开方闭环问题”的第一块真实砖。
2. 启动即用的背后:解压、校验与首次运行的完整链路
2.1 解压与目录结构认知:别急着双击,先看清它装了什么
下载得到的openmrs-standalone-2.3.1.zip是一个自包含压缩包。解压后你会看到如下核心目录:
openmrs-standalone-2.3.1/ ├── openmrs.bat # Windows 启动脚本 ├── openmrs.sh # Linux/macOS 启动脚本 ├── openmrs.jar # 主程序 JAR(含嵌入式 Jetty + OpenMRS Core) ├── openmrs-runtime.properties # 运行时配置(端口、数据库路径、初始用户等) ├── data/ # HSQLDB 数据库存储目录(首次运行自动生成) ├── modules/ # 预装模块目录(如 htmlformentry、reporting、uicommons) └── logs/ # 日志输出目录(启动失败时第一个该查的地方)提示:
openmrs-runtime.properties是整个 Standalone 包的“控制中枢”,后续所有定制化(改端口、换数据库、调初始密码)都从这里开始。不要跳过这一步直接双击——很多翻车源于没看懂这个文件里每行的真实含义。
2.2 环境前置检查:JDK 版本不是“有就行”,而是“必须匹配”
OpenMRS Standalone 2.3.1 基于 Java 8 编译,严格要求运行时 JDK 8u171 及以上版本(低于此版本会触发UnsupportedClassVersionError)。常见误区是认为“我装了 JDK 11,肯定能跑”,但实际会报错:
Exception in thread "main" java.lang.UnsupportedClassVersionError: org/openmrs/web/OpenmrsContext has been compiled by a more recent version of the Java Runtime (class file version 52.0)这是因为openmrs.jar内部 class 文件版本号为 52(对应 Java 8),而 JDK 11 默认拒绝加载低版本 class(安全策略收紧)。解决方案只有两个:
①降级使用 JDK 8(推荐,最稳妥):从 Adoptium 或 Temurin 下载jdk8u392-b08(LTS 最新版),设为系统默认JAVA_HOME;
②强制 JDK 11 兼容模式(不推荐,仅调试用):修改openmrs.bat或openmrs.sh,在java -jar ...命令前加-XX:+IgnoreUnrecognizedVMOptions --add-modules=java.se.ee(JDK 11+ 移除了 Java EE 模块,此参数补全)。
验证方式:终端执行java -version,输出必须为类似java version "1.8.0_392"。
2.3 首次启动与初始化:等待 90 秒,别误判为卡死
双击openmrs.bat(Windows)或终端执行./openmrs.sh(Linux/macOS)后,控制台将输出大量日志。关键观察点有三:
- Jetty 启动成功标志:出现
Started ServerConnector@...和Started @XXXXms(时间戳在 60–90 秒之间); - HSQLDB 初始化完成:出现
HSQL Database Engine和Database opened; - OpenMRS 初始化完成:最后几行是
INFO - InitialModuleActivator.started() - Initialized module: ...,结尾为INFO - WebDaemon.start() - Started OpenMRS on http://localhost:8080/openmrs。
注意:首次启动耗时约 70–110 秒(取决于硬盘速度),期间控制台可能长时间无新日志输出——这是正常现象,HSQLDB 正在导入预置临床数据集(约 1200 条患者记录、800 次就诊、2000 条用药)。若超 150 秒仍无
Started OpenMRS提示,再查日志。
启动成功后,浏览器访问http://localhost:8080/openmrs,输入默认账号:
- 用户名:
admin - 密码:
Admin123(注意大小写和数字)
登录后你将看到完整的 OpenMRS 管理后台:患者注册、登记就诊、填写表单、查看病历、生成报表——所有功能按钮均可用,非灰显。
2.4 验证核心业务流:用 3 分钟走通“挂号→问诊→开方”最小闭环
不要停留在登录页。立即验证真实业务能力:
- 挂号:顶部菜单 →
Register a patient→ 填写姓名、性别、出生日期(必填),点击Register Patient→ 获得患者 ID(如GAN20001); - 问诊:左侧导航 →
Encounters→Create Encounter→ 选择刚注册的患者 →Encounter Type:ADULTINITIAL→ 在表单中填写主诉、现病史、体温、血压(字段自动加载)→Save; - 开方:同一患者页 →
Orders→Add Order→Order Type:Drug Order→ 搜索Paracetamol→ 选中 → 设置剂量500mg、频次TID、疗程5 days→Save。
全部完成后,返回患者首页,点击Medical Record,你能看到结构化展示的就诊记录与处方明细。这证明 Standalone 不仅能启动,其核心数据模型(Patient → Encounter → Obs → Order)已真实贯通,不是静态页面。
3. 从演示走向可用:修改端口、切换数据库、重置密码的三大定制操作
3.1 修改默认端口:避免与本地其他服务(如 XAMPP、Docker)冲突
openmrs-standalone-2.3.1默认监听8080端口。若你本地已有 Tomcat 或 Nginx 占用该端口,启动会失败,日志报错:
ERROR - WebDaemon.start() - Failed to start web server on port 8080 java.net.BindException: Address already in use解决方法:编辑根目录下openmrs-runtime.properties,找到并修改以下两行:
# 修改前 jetty.port=8080 server.url=http://localhost:8080/openmrs # 修改后(例如改为 8090) jetty.port=8090 server.url=http://localhost:8090/openmrs逻辑说明:
jetty.port控制 Jetty 实际监听端口;server.url是 OpenMRS 内部生成跳转链接、API 返回 URL 的依据,两者必须严格一致。改完保存,重启脚本即可。浏览器访问http://localhost:8090/openmrs。
3.2 切换为 MySQL 数据库:告别内存库,为长期使用铺路
HSQLDB 仅适合演示——进程退出即丢数据,且不支持多用户并发。生产级测试需切换至 MySQL。步骤如下:
- 准备 MySQL 环境:确保本地或远程 MySQL 5.7+ 已运行,创建空库
openmrs_standalone,字符集设为utf8mb4; - 修改
openmrs-runtime.properties:注释掉 HSQLDB 配置,添加 MySQL 配置:
# 注释掉原 HSQLDB 行 # runtime.database=hsqldb # runtime.database.location=${app_data_directory}/database # 添加 MySQL 配置(按实际修改 host/user/pass) runtime.database=mysql runtime.database.connection.url=jdbc:mysql://localhost:3306/openmrs_standalone?autoReconnect=true&useSSL=false&zeroDateTimeBehavior=convertToNull&characterEncoding=UTF-8&serverTimezone=GMT%2B0 runtime.database.username=root runtime.database.password=your_mysql_password runtime.database.driver=com.mysql.cj.jdbc.Driver- 下载 MySQL JDBC 驱动:从 MySQL Connector/J 官网 下载
mysql-connector-java-8.0.33.jar,放入openmrs-standalone-2.3.1/lib/目录(若无此目录则新建); - 首次启动初始化:删除
data/目录(清空旧 HSQLDB),运行./openmrs.sh。OpenMRS 会自动检测 MySQL 配置,执行 DDL 创建表结构,并导入初始数据(耗时约 2–3 分钟)。
参数说明:
autoReconnect=true防止连接中断;useSSL=false在本地开发环境可省略证书配置;serverTimezone=GMT%2B0显式指定时区,避免java.sql.SQLException: The server time zone value '...' is unrecognized错误。
3.3 重置管理员密码:当Admin123不再安全时
默认密码Admin123仅用于首次登录。正式使用前必须修改。有两种方式:
方式一:Web 界面修改(推荐,适用于已成功登录)
登录后 → 右上角用户名 →Change Password→ 输入旧密码Admin123,设置新密码(需含大小写字母+数字+特殊字符,长度 ≥8)→Save。
方式二:命令行重置(适用于忘记密码或无法登录)
进入openmrs-standalone-2.3.1/目录,执行:
# Linux/macOS java -cp "openmrs.jar:lib/*" org.openmrs.util.DatabaseUpdater -u admin -p Admin123 -d mysql -c "jdbc:mysql://localhost:3306/openmrs_standalone" -U root -P your_mysql_password --reset-password admin NewPass123!:: Windows(注意分号分隔) java -cp "openmrs.jar;lib/*" org.openmrs.util.DatabaseUpdater -u admin -p Admin123 -d mysql -c "jdbc:mysql://localhost:3306/openmrs_standalone" -U root -P your_mysql_password --reset-password admin NewPass123!逻辑说明:
DatabaseUpdater是 OpenMRS 内置工具类,--reset-password参数直连数据库更新users表中admin用户的password字段(加密存储)。-U/-P是 MySQL root 凭据,-c是数据库连接串。执行后重启服务即可用NewPass123!登录。
4. 避坑指南:那些让开发者抓狂却文档里找不到的五个真实陷阱
4.1 现象:启动后浏览器打开白页,控制台无报错,Network 面板显示http://localhost:8080/openmrs/login.htm404
原因:openmrs-runtime.properties中server.url末尾漏写了/openmrs,或写成了/openmrs/(多了一个斜杠)。OpenMRS 依赖此 URL 构造所有前端资源路径,错误会导致 JS/CSS 加载失败。
解决:检查server.url必须为http://localhost:8080/openmrs(无尾斜杠),且与jetty.port一致。改完重启。
4.2 现象:登录成功后,点击Register a patient报错Error 500: javax.servlet.ServletException: java.lang.NoClassDefFoundError: org/apache/commons/lang3/StringUtils
原因:openmrs.jar依赖commons-lang3,但 Standalone 包中该 JAR 缺失或版本不匹配(常见于手动替换 JAR 后未同步依赖)。
解决:下载commons-lang3-3.12.0.jar,放入lib/目录;若已存在,检查是否为3.12.0版本(jar -tf commons-lang3-*.jar | head -5查看内部 class)。重启。
4.3 现象:切换 MySQL 后首次启动卡在Initializing database...超过 5 分钟,日志停在Running liquibase update...
原因:MySQL 未开启innodb_file_per_table=ON,或max_allowed_packet过小(<16M),导致大 SQL(如临床术语词典导入)执行失败。
解决:登录 MySQL 执行:
SET GLOBAL innodb_file_per_table = ON; SET GLOBAL max_allowed_packet = 64*1024*1024;并在my.cnf中永久配置。然后删除data/目录,重启 Standalone。
4.4 现象:在Encounters表单中输入中文,保存后显示乱码(如æ£è 主è¯),但数据库里存的是正常中文
原因:Jetty 未设置 URI 编码,URL 参数(如表单提交)被 ISO-8859-1 解码。
解决:编辑openmrs-runtime.properties,添加:
jetty.uri.encoding=UTF-8重启生效。
4.5 现象:使用 Chrome 访问http://localhost:8080/openmrs提示Your connection is not private,地址栏显示红色警告
原因:Standalone 默认启用 HTTPS 重定向(openmrs-runtime.properties中server.use.https=true),但未提供有效证书,浏览器拒绝不安全的自签名证书。
解决:编辑openmrs-runtime.properties,设server.use.https=false,并确保server.url为http://开头。重启后即可用 HTTP 正常访问。
5. 模块热插拔实战:给 Standalone 加上「门诊电子处方」与「检验报告查看」能力
5.1 理解 OpenMRS 模块机制:WAR vs OMOD,为什么 Standalone 只认 OMOD
OpenMRS 功能扩展通过.omod文件实现(OpenMRS Module,本质是 ZIP 包,含config.xml、moduleApplicationContext.xml、编译后的 class 和资源)。Standalone 内嵌的 Jetty 不支持传统 WAR 部署,只识别modules/目录下的.omod文件。官方模块库( modules.openmrs.org )提供两类下载:
xxx-1.2.3.omod:可直接放入modules/;xxx-1.2.3.zip:需解压后找到.omod文件(通常在omod/子目录)。
关键区别:OMOD 是 OpenMRS 运行时动态加载的插件,无需重启服务(部分模块需重启);而 WAR 是 Servlet 容器部署单元,Standalone 的 Jetty 未暴露 WAR 部署接口。
5.2 安装「门诊电子处方」模块(htmlformentryui)
该模块提供可视化拖拽表单设计器,是构建门诊电子处方的核心。步骤:
- 下载模块:访问 htmlformentryui 4.5.0 下载页 ,保存为
htmlformentryui-4.5.0.omod; - 放置模块:将
.omod文件复制到openmrs-standalone-2.3.1/modules/目录; - 重启服务:执行
./openmrs.sh,启动日志中会出现INFO - ModuleUtil.loadModule() - Loaded module: htmlformentryui 4.5.0; - 验证安装:登录后 →
System Administration→Manage Modules→ 查看HTML Form Entry UI状态为Active; - 启用处方功能:
System Administration→HTML Form Entry→Manage HTML Forms→ 点击Add Form→ 选择Encounter Type:ADULTINITIAL→ 在表单设计器中拖入「药品名称」「剂量」「用法」「疗程」字段 →Save。
参数说明:
ADULTINITIAL是 OpenMRS 预定义的成人初诊就诊类型,所有门诊表单必须绑定到具体Encounter Type。htmlformentryui依赖htmlformentry(已预装),若提示缺失,需一并下载htmlformentry-4.5.0.omod放入modules/。
5.3 安装「检验报告查看」模块(labintegration)
该模块对接 LIS 系统,展示结构化检验结果。因 Standalone 2.3.1 较老,需选用兼容版本:
- 下载兼容版:
labintegration-2.10.0.omod(适配 OpenMRS 2.3.x),从 labintegration 2.10.0 发布页 获取; - 处理依赖冲突:
labintegration依赖webservices.rest-2.24.0,但 Standalone 自带webservices.rest-2.22.0。需先删除modules/webservices.rest-2.22.0.omod,再放入webservices.rest-2.24.0.omod和labintegration-2.10.0.omod; - 重启并激活:重启后,在
Manage Modules中确认两者均为Active; - 模拟检验数据:
System Administration→Lab Integration→Manage Lab Tests→Add Test→ 创建CBC(血常规)模板 →Manage Lab Results→Add Result→ 为某患者录入 WBC、HGB 等值 → 返回患者首页,Lab Results标签页即可见报告。
5.4 模块卸载与回滚:当新模块引发崩溃时的后悔药
模块安装出错(如依赖不满足、版本冲突)可能导致 OpenMRS 启动失败,日志报Failed to start module xxx。此时不要删整个modules/:
- 定位问题模块:查看日志中
Failed to start module后的模块名(如htmlformentryui); - 临时移除:将对应
.omod文件从modules/移出到其他目录(如modules_backup/); - 清理缓存:删除
openmrs-standalone-2.3.1/data/work/目录(Jetty 编译缓存,避免残留 class 加载失败); - 重启验证:服务应恢复正常。待问题模块修复(如下载正确版本)后再放回
modules/。
血泪经验:我曾在某次培训中因误装
htmlformentryui-5.0.0(需 OpenMRS 2.4+)导致全场学员环境瘫痪。从那以后,我每次添加模块前都强制执行ls modules/ && java -cp "openmrs.jar" org.openmrs.module.ModuleUtil.listModules(列出当前已加载模块),确认版本兼容性再重启——这 30 秒检查,省去 2 小时排错。
6. 生产就绪前的最后一道关卡:日志分析、性能基线与安全加固三步法
6.1 日志分级与关键错误捕获:从logs/openmrs.log里挖出真问题
Standalone 默认日志级别为INFO,但关键故障往往藏在WARN和ERROR中。高效排查需掌握日志结构:
| 日志行示例 | 解读 |
|---|---|
ERROR - DatabaseUpdater.updateDatabase() - Error running liquibase update | 数据库迁移失败,检查openmrs-runtime.properties数据库配置及 MySQL 权限 |
WARN - HtmlFormEntryService.getHtmlFormByUuid() - No form found with uuid: xxx | 表单 UUID 不存在,检查Manage HTML Forms中是否已发布该表单 |
ERROR - WebDaemon$1.run() - Failed to start web server on port 8080 | 端口被占用,执行netstat -ano | findstr :8080(Windows)或lsof -i :8080(macOS/Linux)查进程 |
实用技巧:用
tail -f logs/openmrs.log \| grep -E "(ERROR|WARN)"实时监控错误;对启动失败场景,用grep -A 5 -B 5 "Exception" logs/openmrs.log查看异常堆栈上下文。
6.2 性能基线测试:量化 Standalone 的真实承载力
Standalone 不是玩具,但需明确其边界。我在某次压力测试中用 JMeter 模拟 50 并发用户执行「挂号→问诊→开方」全流程,记录关键指标:
| 场景 | 硬件配置 | 平均响应时间 | 错误率 | 备注 |
|---|---|---|---|---|
| HSQLDB(默认) | i5-8250U / 16GB / SSD | 1200ms | 0% | 仅限单用户演示,50 并发下 CPU 占用 95%+ |
| MySQL 5.7(本地) | 同上 | 420ms | 0% | 连接池默认 20,50 并发稳定 |
| MySQL 5.7(远程) | 同上 + 100ms 网络延迟 | 1350ms | 2.3% | 超时集中在saveEncounter,需调大wait_timeout |
配置优化项(写入
openmrs-runtime.properties):
# MySQL 连接池调优(适配 50 并发) runtime.database.connection.pool.maxActive=50 runtime.database.connection.pool.maxIdle=20 runtime.database.connection.pool.minIdle=5 # HSQLDB 仅用于演示,不建议调优结论:Standalone 在本地 MySQL 下可稳定支撑 30–40 并发的基层门诊场景(日均 200–300 人次),超出此规模需升级为标准 WAR 部署 + PostgreSQL + Redis 缓存。
6.3 安全加固四件套:关闭调试、限制 IP、启用 CSRF、审计登录
默认配置面向开发,生产前必须加固:
- 关闭调试模式:
openmrs-runtime.properties中设debug=false,禁用Spring调试端点; - 限制管理后台访问 IP:在
openmrs-runtime.properties添加:# 只允许本地和内网访问 security.allowed.ips=127.0.0.1,192.168.1.0/24 - 启用 CSRF 保护(防跨站请求伪造):确保
openmrs-runtime.properties中security.csrf.enabled=true(默认开启,勿关闭); - 开启登录审计:添加配置:
# 记录所有登录尝试(成功/失败) security.audit.login=true # 审计日志输出到独立文件 log4j.logger.org.openmrs.security.audit=INFO, AUDIT log4j.appender.AUDIT=org.apache.log4j.RollingFileAppender log4j.appender.AUDIT.File=logs/audit.log
重要提醒:
security.allowed.ips是 OpenMRS 内置过滤器,无需 Apache/Nginx 配置。它会在AuthenticationFilter中拦截非授权 IP 的/openmrs/login.htm请求,返回 403。这是 Standalone 环境最简单有效的网络层防护。
从那以后我每次交付 Standalone 环境给客户前,都强制走一遍这三步:tail -f logs/openmrs.log监控启动、jmeter -n -t test-plan.jmx跑 30 并发基线、grep -r "security\|debug\|allowed" openmrs-runtime.properties三重核对安全配置。少一次,就可能让一个本该顺利上线的社区诊所系统,在验收当天因为一个未关闭的调试端点被扫出漏洞。希望帮到你。
本文还有配套的精品资源,点击获取