jeeflow 系列 · 第 2 篇(认识季)
先感受一下 98KB 是什么概念:
- 一张高清手机照片,普遍 2
5MB,是它的 2050 倍; - 一个中文字体文件,动辄几十 MB;
- 你在浏览器里加载的某个 JS 框架,可能都比它大。
而 jeeflow 的整个引擎核心,只有 98KB ------上一篇文章里,我们讲了为什么在 Flowable 时代还要自研轻量引擎(选型账见第 1 篇)。这篇直接拆开看:一个零依赖的工作流引擎,里面到底装了什么,凭什么能跑审批?
本文内容对齐 jeeflow v1.8.11(四语言 + 文档站同步版本,已发布 Maven Central / PyPI / npm / Go proxy)。本系列由 mldong 快速开发框架生态延续而来,建议按顺序阅读:第 0 篇讲来龙去脉,第 1 篇讲选型,本篇讲"是什么"。
一、整体长这样:核心 + 周边,边界清晰
jeeflow-java 仓库按职责分模块,引擎核心与周边严格隔离:
sql
jeeflow-core ← 引擎核心,98KB,仅依赖 slf4j-api(provided)
├── 引擎入口:start / execute / jump 等 5 个方法
├── DDD 聚合根:ProcessInstance / ProcessTask
├── 节点处理器:task / decision / fork / join / countersign / custom
├── SPI 体系(见第三节)
└── 状态机:实例 7 态 · 任务 6 态(v1.4.0 起对齐 boot3 全量枚举)
jeeflow-repository-jdbc ← 纯 JDBC 仓储实现(8 张表,白名单防注入)
jeeflow-persist ← 业务数据入库(SYNC 同步演进 + 元数据驱动读写,v1.6.2+)
jeeflow-spring-boot-autoconfigure ← Spring 自动装配 + m_* 查询解析
jeeflow-spring-boot2/3/4-starter ← Boot 2.x / 3.x / 4.x 三个 Starter
jeeflow-demo-boot4 ← 演示站(对接统一前端 jeeflow-ui)
关键设计:引擎核心不认识 Spring,不认识 MyBatis,不认识 JSON 库。 它只认接口------这就是 98KB 的秘密。
二、5 行代码跑起来
Java 里,一个完整可运行的引擎实例长这样(摘自 README):
java
Configuration config = new Configuration();
ServiceContext.put("repository", new MemoryProcessRepository());
ServiceContext.put("json", new BuiltinJsonProvider());
JeeflowEngine engine = new JeeflowEngineImpl();
engine.configure(config);
ProcessInstance pi = engine.startProcessInstanceById(defineId, "张三", FlowData.create());
没有 Spring 启动、没有 XML、没有建表脚本,内存仓储 + 内置 JSON 解析器直接跑。要接数据库?换一个仓储实现即可------引擎这边一行不用改。
三、零依赖的秘密:SPI 体系
引擎核心不依赖任何具体技术,因为它把"会变的环节"全部抽象成了接口。以 v1.8.4 为准,SPI 分三层:
核心 6 大 SPI(引擎运行必需/常用):
| SPI 接口 | 职责 | 必须 |
|---|---|---|
IProcessRepository |
聚合仓储(define/instance/task/task_actor/cc 5 核心表) | ✅ |
IJsonProvider |
JSON 解析(引擎核心不绑定 JSON 库) | ✅ |
IUserProvider |
用户信息(一次取回 userId/realName/dept/post) | 可选 |
IExpressionEvaluator |
决策/会签表达式求值 | 可选 |
IIdGenerator |
ID 生成 | 可选 |
ITransactionTemplate |
事务模板(引擎不感知事务,业务层包裹) | 可选 |
能力扩展 SPI(按需接入):
| SPI | 版本 | 职责 |
|---|---|---|
IOrgUserProvider |
v1.6.0 | 组织取人:部门领导 / 分管领导 / 按角色 |
IUserSearchProvider |
v1.2.0 | 执行候选人分页搜索 |
IDynamicMetaProvider |
v1.7.0 | 元数据提供(持久化读写共用) |
IActionPermissionProvider |
v1.8.3 | 门面 action 权限码(默认 wf:{action:/→:}) |
IProcessExtRepository |
v1.1.0 | 管理扩展仓储(设计/历史/委托) |
想用 Fastjson 用 Fastjson,想用 Jackson 用 Jackson;想接 MySQL 接 MySQL,想内存跑测试就内存------替换任意环节,引擎不动。 这就是"零依赖"的完整含义:不是没依赖,是依赖全部可插拔。
四、数据:5 张核心表 + 3 张管理表
数据库层同样克制:核心 5 张表(wf_process_define / wf_process_instance / wf_process_task / wf_process_task_actor / wf_process_cc_instance),v1.1.0 起管理扩展加 3 张(wf_process_design / wf_process_design_his / wf_process_surrogate 设计稿/历史/委托)------总共 8 张,对比 Flowable 的 70+ 张,schema 一目了然。
五、DDD 充血模型:状态转换是领域行为
引擎不是"操作数据库的 CRUD 脚本",而是 DDD 的充血模型:
ProcessInstance(聚合根) :持有实例状态与任务列表,封装所有命令行为------completeTask、finish、reject、abandonAllDoing......状态怎么变,由聚合根说了算;ProcessTask(子实体) :任务自己的行为------finish(完成)、abandon(废弃)、isAllowed(权限判断)。
状态机是双层的,而且比大多数人想象的完整:实例 7 态 (进行中/已完成/已拒绝 + 撤回/终止/挂起/废弃),任务 6 态(待办/已完成/已废弃 + 撤回/终止/挂起级联)。下一篇《工作流引擎的"灵魂"》专门拆这个。
六、内置 9 种流程模式 + 一份统一门面
开始、结束、任务、决策(表达式路由)、分支(fork)、合并(join)、子流程、自定义节点(customClass 业务接管)、会签(并行/串行/按比例)------覆盖业务系统里 95% 以上的审批场景。
引擎之上还有一层 JeeflowFacade.flow(action, map) 统一门面 (v1.1.0 起,现含 40 个 action ):对齐 boot2/boot3 全部端点------定义/实例/任务/设计/委托/视图。集成方只需要一个转发 controller,把 body JSON 传进门面,一行代码接完所有流程能力。这是"契约对齐"的工程化体现(详见第 4 季)。
七、它不只是一个 Java 库
jeeflow 的引擎语义同时存在于 Java / Go / Python / Node 四个实现里,同一份流程 JSON 在四种语言上跑出相同结果,前端 jeeflow-ui 一套对接四套后端。98KB 是 Java 核心的尺寸,但它背后的"多语言联邦",是这个项目真正的差异化------那是第三季的故事。
结语
98KB 装得下什么?装得下一个 DDD 设计的引擎核心、可插拔的 SPI 体系、9 种流程模式、7+6 双层状态机------装不下的是任何框架包袱。而且它六天内从 1.0.0 演进到 1.8.11(管理扩展、持久化、元数据、权限体系、门面 40 action 全接口文档),核心还是 98KB。
下一篇预告:《工作流引擎的"灵魂":状态机与 submitType》------实例为什么有 7 种状态?8 种提交类型怎么驱动状态流转?退回、跳转、会签否决的底层逻辑一次讲透。
相关链接
- jeeflow 文档站:jeeflow-doc.mldong.com
- 引擎仓库(GitHub · mldong 组织):
jeeflow-java/jeeflow-go/jeeflow-python/jeeflow-node/jeeflow-ui