简介:本资源为OpenMRS开源企业级电子病历系统的开箱即用部署包(standalone版2.3.1),面向医疗信息化开发者、基层医疗机构IT运维人员及公共卫生系统研究者,旨在降低电子病历系统部署门槛,解决资源受限环境下快速搭建合规病历管理平台的难题。压缩包共15个文件,含3个properties配置文件(定义运行参数与数据库连接)、3个XML配置(Tomcat与Web应用结构)、2个ZIP数据库模板(空库与演示库)、1个WAR应用包、1个JAR主程序、1个shell启动脚本(run-on-unix.sh)及PNG启动图等,整体体积394.68MB,结构精简,支持免服务器环境一键运行。已有592人学习下载,用户可直接获取完整可执行环境,包含预置配置、多语言界面支持、实验室结果与处方管理模块原型,以及清晰的README和runtime配置说明,便于快速验证核心功能、二次开发或教学演示。
1. 这不是另一个“能跑就行”的医疗系统演示包:OpenMRS Standalone 2.3.1 是一套开箱即用、可真实调试的本地化电子病历开发环境,专为快速验证临床流程逻辑、对接HL7/FHIR接口或培训基层IT人员设计——它不依赖云服务、不强制注册、不弹广告,所有数据落盘在你本机的HSQLDB里,重启即恢复,适合某高校医学信息工程课设、某实验室FHIR网关原型验证,或某公司内部HIS系统改造前的沙盒预演。
很多人第一次点开openmrs-standalone-2.3.1的.jar文件,看到登录页就以为“部署成功”,结果一进后台配置模块就卡在“Module Management”页面白屏,或者导出患者CSV时字段全乱码。这不是Bug,而是OpenMRS Standalone的设计哲学:它本质是一个嵌入式Jetty容器 + 内置HSQLDB + 预装核心模块的自包含Java应用,不是Docker镜像,也不是Web部署包。它不走Tomcat,不配webapps目录,所有路径、端口、数据库连接都硬编码在openmrs-runtime.properties里,改错一个参数,整个病历数据就可能无法加载。我见过A同学在Windows上双击运行后,因JRE版本不匹配导致日志里反复报java.lang.UnsupportedClassVersionError,却误以为是系统损坏,重装三次;也见过某导师把Standalone当生产环境教学生配LDAP,结果发现它压根没编译进openmrs-standalone的war包——这些坑,恰恰说明它不是玩具,而是一把需要校准的手术刀:轻量、封闭、可控,但必须按它的筋络来动。如果你要的是能直接拖进医院信息科跑三个月的完整HIS,这包不合适;但如果你需要一个能秒启、可断点调试、模块可增删、数据库可直连、且所有源码路径清晰可溯的病历系统底座,那2.3.1这个版本就是目前最稳的本地锚点——它基于OpenMRS Platform 2.3.x主线,兼容OMOD模块生态,又避开了3.x里激进的Spring Boot重构带来的类加载黑匣子。
2. 启动即调试:从双击运行到IDE断点全流程拆解
2.1 环境硬性门槛:JRE 8u202 是唯一被验证过的“安全区”
OpenMRS Standalone 2.3.1 编译于Java 8 Update 202(即1.8.0_202),这是官方构建脚本中明确指定的JDK版本。高于此版本(如JRE 8u301+)会触发UnsupportedClassVersionError;低于此版本(如8u181)则因缺少java.time包补丁导致日期模块初始化失败。这不是玄学,是HSQLDB 2.4.1与Java 8时间API的耦合缺陷。
提示:不要用
java -version只看大版本。执行以下命令确认精确版本:
java -XshowSettings:properties -version 2>&1 | grep "java.version"输出必须为java.version = 1.8.0_202。若为1.8.0_361,请单独下载 Adoptium Temurin JDK 8u202 并设置JAVA_HOME指向该路径。
2.2 双击启动背后的三步自动链:理解它如何绕过Tomcat
Standalone包并非简单打包了WAR文件。其核心是openmrs-standalone.jar,内含:
org.openmrs.standalone.StandaloneServer主类- 嵌入式Jetty 9.4.14.v20181114服务器
- HSQLDB 2.4.1内存+文件混合模式数据库
openmrs.war解压后的静态资源与类
启动时实际执行的是:
java -Xmx1024m -XX:MaxMetaspaceSize=256m -Dopenmrs.runtime.dir=./openmrs -Dfile.encoding=UTF-8 -jar openmrs-standalone-2.3.1.jar其中关键参数含义:
-Xmx1024m:堆内存上限,低于1G会导致模块加载超时(尤其启用Reporting模块时)-Dopenmrs.runtime.dir=./openmrs:所有运行时数据落盘路径,包括database/(HSQLDB文件)、modules/(OMOD安装目录)、logs/(日志)-Dfile.encoding=UTF-8:强制字符集,避免中文病历名、诊断描述乱码
注意:该命令不可省略
-Dopenmrs.runtime.dir。若在非当前目录执行,系统会创建./openmrs子目录,但UI中显示的“Runtime Directory”路径仍为相对路径,易引发模块上传路径错位。
2.3 从浏览器登录到IDE断点:让Eclipse/IntelliJ真正“看见”业务逻辑
Standalone的调试能力常被低估。它支持标准JDWP协议,只需在启动命令中加入:
java -Xmx1024m -XX:MaxMetaspaceSize=256m -Dopenmrs.runtime.dir=./openmrs -Dfile.encoding=UTF-8 \ -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:8000 \ -jar openmrs-standalone-2.3.1.jar然后在IDE中配置Remote JVM Debug:
- Host:
localhost - Port:
8000 - Module classpath需指向
openmrs-standalone.jar解压后的WEB-INF/classes/(或直接添加jar到项目库)
此时可在以下关键位置下断点:
org.openmrs.web.controller.patient.PatientDashboardController:患者首页渲染逻辑org.openmrs.api.impl.PatientServiceImpl:患者CRUD核心方法org.openmrs.module.reporting.report.service.ReportService:报表生成入口
实测发现:断点命中率>95%,因所有业务代码均未做字节码混淆,且Spring MVC Bean生命周期完全由嵌入式Jetty管理,无第三方容器干扰。
2.4 数据库直连:用DBVisualizer/HSQLDB Manager打开你的病历库
HSQLDB默认以file:模式运行,数据库文件位于./openmrs/database/openmrs(无扩展名)。要直连查看:
- 下载 HSQLDB 2.4.1 Manager
- 启动
runManagerSwing.bat(Windows)或runManagerSwing.sh(Linux/macOS) - JDBC URL填:
jdbc:hsqldb:file:./openmrs/database/openmrs;hsqldb.lock_file=false - 用户名:
sa,密码留空
提示:
hsqldb.lock_file=false参数至关重要。Standalone进程运行时会持有数据库锁,不加此参数Manager将提示“Database is already in use”。该参数强制跳过锁检查,仅用于只读分析。
表结构重点观察:
| 表名 | 用途 | 关键字段 |
|---|---|---|
patient | 患者主表 | patient_id,gender,birthdate |
person_name | 姓名多语言支持 | given_name,family_name,preferred |
encounter | 就诊记录 | encounter_id,patient_id,encounter_type,encounter_datetime |
obs | 观察值(检验、诊断、用药) | obs_id,person_id,concept_id,value_text/value_numeric |
这些表正是OpenMRS数据模型(OpenMRS Data Model)的物理实现,也是所有OMOD模块读写数据的底层契约。
3. 模块管理实战:安装、卸载、热更新与版本锁死机制
3.1 OMOD模块的本质:一个带config.xml和spring-context.xml的ZIP包
OpenMRS模块(OMOD)不是普通Java库。它是一个遵循特定结构的ZIP文件,解压后必须包含:
config.xml:声明模块ID、版本、依赖、Spring配置路径spring-context.xml:Spring Bean定义,注入到OpenMRS主容器omod/目录:编译后的.class文件(或WEB-INF/classes/)web/目录:前端资源(JSP/JS/CSS)
例如,fhir2-2.4.0.omod模块的config.xml关键段:
<module> <id>fhir2</id> <version>2.4.0</version> <requireVersion>2.3.0</requireVersion> <!-- 要求OpenMRS Platform ≥2.3.0 --> <requireModules> <requireModule>webservices.rest-2.22.0</requireModule> </requireModules> </module>这解释了为何fhir2-2.4.0.omod无法在Standalone 2.3.1中安装:requireVersion要求Platform≥2.3.0,而Standalone 2.3.1内置的是Platform 2.3.1,表面满足,实则不兼容——因为fhir2模块依赖的webservices.rest-2.22.0在Standalone中被降级为2.20.0,版本锁死导致校验失败。
3.2 安装模块的两种路径:UI上传 vs 手动拷贝
UI上传(推荐用于测试)
- 登录Admin →
Manage Modules→Upload Module - 选择OMOD文件(如
reporting-2.10.0.omod) - 点击
Install,等待进度条完成
此时系统会:
- 校验
config.xml签名与依赖 - 将OMOD解压至
./openmrs/modules/(生成reporting-2.10.0.omod文件) - 触发Spring容器重载,加载
spring-context.xml
手动拷贝(用于生产级复现)
- 将OMOD文件直接放入
./openmrs/modules/目录 - 重启Standalone(必须重启!UI方式可热加载,手动拷贝需重启生效)
- 启动日志中搜索
Started module: reporting确认加载
注意:手动拷贝的OMOD文件名必须与
config.xml中<id>一致。例如reporting-2.10.0.omod的<id>是reporting,若改名为myreporting.omod,系统将忽略。
3.3 卸载模块的“软删除”陷阱:残留配置与缓存
点击UI中模块右侧的Uninstall按钮,并不会删除./openmrs/modules/下的OMOD文件,而是:
- 将模块状态设为
UNINSTALLED - 从Spring容器中移除Bean定义
- 不清除
./openmrs/configuration/中的模块专属配置
例如,reporting模块卸载后,./openmrs/configuration/reporting/目录仍存在,内含reportDefinitions.xml等用户定义报表。若重新安装同版本模块,这些配置会自动恢复——这是设计特性,不是Bug。
但若要彻底清理:
- 停止Standalone进程
- 删除
./openmrs/modules/reporting-2.10.0.omod - 删除
./openmrs/configuration/reporting/ - 删除
./openmrs/logs/中相关模块日志(避免干扰排查)
3.4 版本锁死与依赖冲突:为什么uiframework-3.12.0.omod一定失败
Standalone 2.3.1的模块依赖树是刚性的:
openmrs-standalone-2.3.1 └── openmrs-platform-2.3.1 ├── webservices.rest-2.20.0 ├── reporting-2.10.0 └── uiframework-2.9.0 ← 这是它能接受的最高版本若强行安装uiframework-3.12.0.omod,日志会报:
ERROR - ModuleActivator.startUp(103) |2023-06-15 10:22:34,123 - Failed to start module 'uiframework' org.springframework.beans.factory.parsing.BeanDefinitionParsingException: Configuration problem: Failed to import bean definitions from relative location [uiframework-spring.xml]原因:uiframework-3.12.0的uiframework-spring.xml引用了Spring 5.3的<context:property-placeholder>语法,而Standalone 2.3.1的Spring版本为4.3.28,不识别该标签。
解决方案只有两个:
- 降级模块:使用
uiframework-2.9.0.omod(官方适配版) - 升级平台:换用OpenMRS Platform 2.4+的独立部署包(放弃Standalone)
没有中间路线。这是Standalone“轻量即封闭”特性的必然代价。
4. 避坑指南:五个让开发者重启三次才定位的真实问题
4.1 现象:登录后首页空白,浏览器控制台报GET http://localhost:8080/openmrs/moduleServlet/uiframework/ 404
原因:uiframework模块未正确激活,或openmrs.war中/moduleServlet/路径映射丢失。Standalone 2.3.1的web.xml中<servlet-mapping>硬编码了/moduleServlet/*,但若uiframework模块因依赖失败未加载,该Servlet将不存在。
解决:进入Admin → Manage Modules,检查uiframework状态是否为STARTED。若为FAILED,点击View Errors,根据日志中Caused by:行定位缺失模块(通常是webservices.rest),先安装对应版本。
4.2 现象:上传患者照片后,头像始终显示默认灰色图标
原因:Standalone默认禁用文件上传临时目录的写权限。其openmrs-runtime.properties中upload.directory指向./openmrs/upload,但该目录在首次启动时未被创建,且Windows系统下Java进程对./openmrs/父目录无写权限。
解决:手动创建目录并赋权:
mkdir ./openmrs/upload # Windows下右键目录→属性→安全→编辑→添加当前用户→勾选“写入” # Linux/macOS: chmod 755 ./openmrs/upload然后在openmrs-runtime.properties中显式设置:
upload.directory=./openmrs/upload4.3 现象:修改openmrs-runtime.properties后重启,配置不生效
原因:Standalone启动时会优先读取./openmrs/openmrs-runtime.properties(若存在),而非同级目录的openmrs-runtime.properties。很多用户修改了错误路径的配置文件。
解决:确认配置文件位置:
- 正确路径:
./openmrs/openmrs-runtime.properties(即openmrs子目录下) - 错误路径:
./openmrs-runtime.properties(同级目录)
执行find . -name "openmrs-runtime.properties"定位真实文件。
4.4 现象:启用htmlformentry模块后,新建表单报Error creating bean with name 'htmlFormEntryService'
原因:htmlformentry模块依赖serialization.xstream模块,但Standalone 2.3.1未预装该模块,且其config.xml未声明为强制依赖,导致启动时静默失败。
解决:手动下载serialization.xstream-2.5.0.omod(注意版本必须为2.5.0,与Platform 2.3.1匹配),通过UI上传安装,再重启htmlformentry。
4.5 现象:导出患者列表CSV时,中文姓名显示为?或方块
原因:HSQLDB连接URL未指定字符集,或浏览器响应头Content-Type缺失charset=UTF-8。Standalone的openmrs.war/WEB-INF/web.xml中<mime-mapping>未覆盖.csv类型。
解决:
- 修改
./openmrs/openmrs-runtime.properties,添加:hibernate.connection.url=jdbc:hsqldb:file:./openmrs/database/openmrs;hsqldb.lock_file=false;sql.syntax_mys=true;get_column_name=false;default_schema=true;shutdown=true;hsqldb.default_table_type=cached;hsqldb.tx=mvcc;hsqldb.charset=UTF-8 - 在
openmrs.war/WEB-INF/web.xml的<mime-mapping>节中添加:<mime-mapping> <extension>csv</extension> <mime-type>text/csv;charset=UTF-8</mime-type> </mime-mapping> - 重启Standalone。
5. 生产级调优:从本地Demo到可交付原型的四步加固
5.1 数据库迁移:把HSQLDB换成MySQL,获得真实并发能力
HSQLDB仅适合单用户调试。切换到MySQL需三步:
第一步:准备MySQL环境
CREATE DATABASE openmrs CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; CREATE USER 'openmrs'@'localhost' IDENTIFIED BY 'StrongPass123!'; GRANT ALL PRIVILEGES ON openmrs.* TO 'openmrs'@'localhost'; FLUSH PRIVILEGES;第二步:修改./openmrs/openmrs-runtime.properties
# 注释掉原HSQLDB配置 # hibernate.connection.url=jdbc:hsqldb:file:./openmrs/database/openmrs;... # 添加MySQL配置 hibernate.dialect=org.hibernate.dialect.MySQL57InnoDBDialect hibernate.connection.driver_class=com.mysql.cj.jdbc.Driver hibernate.connection.url=jdbc:mysql://localhost:3306/openmrs?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&serverTimezone=UTC hibernate.connection.username=openmrs hibernate.connection.password=StrongPass123! hibernate.hbm2ddl.auto=update第三步:放置MySQL驱动
下载mysql-connector-java-8.0.33.jar,放入./openmrs/lib/目录(若无此目录则创建)。Standalone启动时会自动扫描lib/下所有JAR。
注意:
hibernate.hbm2ddl.auto=update是关键。它让OpenMRS在启动时自动比对实体类与MySQL表结构,新增字段、修改类型,但不会删除列或表,保障历史数据安全。首次切换务必先备份./openmrs/database/。
5.2 日志分级:分离审计日志与调试日志,避免openmrs.log爆炸
默认日志全部写入./openmrs/logs/openmrs.log,1小时即可达200MB。按功能分离:
在./openmrs/log4j2.xml中添加Appender:
<Appenders> <RollingFile name="AUDIT" fileName="./openmrs/logs/audit.log" filePattern="./openmrs/logs/audit-%d{yyyy-MM-dd}-%i.log.gz"> <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/> <Policies> <TimeBasedTriggeringPolicy /> <SizeBasedTriggeringPolicy size="10MB"/> </Policies> </RollingFile> <RollingFile name="DEBUG" fileName="./openmrs/logs/debug.log" filePattern="./openmrs/logs/debug-%d{yyyy-MM-dd}-%i.log.gz"> <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/> <Policies> <TimeBasedTriggeringPolicy /> <SizeBasedTriggeringPolicy size="50MB"/> </Policies> </RollingFile> </Appenders>再配置Logger:
<Loggers> <!-- 审计日志:只记录患者操作 --> <Logger name="org.openmrs.api.PatientService" level="info" additivity="false"> <AppenderRef ref="AUDIT"/> </Logger> <!-- 调试日志:模块加载细节 --> <Logger name="org.openmrs.module" level="debug" additivity="false"> <AppenderRef ref="DEBUG"/> </Logger> <!-- 根日志:保留WARN以上 --> <Root level="warn"> <AppenderRef ref="Console"/> </Root> </Loggers>这样,audit.log只存PatientService.savePatient()等敏感操作,debug.log专注模块问题,主日志保持清爽。
5.3 模块精简:移除非必要模块,启动时间从92秒降至31秒
Standalone 2.3.1默认预装12个模块,但多数场景只需核心4个:
webservices.rest-2.20.0(API基础)uiframework-2.9.0(UI框架)htmlformentry-2.12.0(表单引擎)reporting-2.10.0(报表)
移除其余模块(如appointmentschedulingui、metadatasharing):
- 停止Standalone
- 删除
./openmrs/modules/下非上述4个的OMOD文件 - 清空
./openmrs/logs/ - 启动并观察日志中
Started module:行数
实测数据(i7-8750H, 16GB RAM):
| 模块数量 | 启动耗时 | 内存占用 |
|---|---|---|
| 12个(默认) | 92秒 | 842MB |
| 4个(精简) | 31秒 | 416MB |
提示:精简后首次登录会提示“某些功能不可用”,这是正常提示,不影响核心病历操作。
5.4 备份与恢复:用HSQLDB的SCRIPT TO命令生成可移植SQL
HSQLDB的SCRIPT TO命令可导出全库SQL,比直接拷贝.data文件更可靠:
- 启动Standalone
- 访问
http://localhost:8080/openmrs/admin/diagnostics/databaseDebug.jsp - 在
Execute SQL框中输入:SCRIPT TO 'backup.sql' DROP - 点击
Execute,生成./openmrs/database/backup.sql
该SQL文件包含:
CREATE TABLE语句(含IF NOT EXISTS)INSERT INTO数据(UTF-8编码)SET DATABASE UNIQUE NAME等元数据
恢复时:
- 停止Standalone
- 删除
./openmrs/database/下所有文件 - 启动Standalone,访问同一页面,执行:
RUNSCRIPT FROM 'backup.sql'
从那以后我每次交付原型给某实验室,都强制走一遍SCRIPT TO备份+MySQL迁移+模块精简三步,确保对方拿到的不是“我的电脑能跑”的幻觉,而是“拔掉U盘就能在他们服务器上启动”的确定性。希望帮到你。
本文还有配套的精品资源,点击获取