变量序列化是挂起任务的前提,引擎必须将流程实例及各作用域变量全部序列化落库,否则挂起失败;全局变量全量序列化,局部变量独立序列化,外部变量须可被识别;禁用不可序列化对象、自定义类实现Serializable、敏感字段用transient、大对象存ID而非内容。
挂起任务时,变量状态的完整保存不是“自动发生”的附加动作,而是序列化机制在底层承担的关键职责。它确保流程被冻结后,所有上下文数据不丢失、不混淆,恢复时能精准回到断点。
变量序列化是挂起操作的前提条件
工作流引擎(如Activiti、Camunda、SpiffWorkflow)在执行挂起前,必须将当前流程实例及其所有作用域(流程实例、子执行、任务)中的变量全部序列化并落库。这不是可选步骤,而是挂起生效的必要条件:
未序列化的变量在挂起后会丢失,激活时无法还原
引擎不会对未声明为可序列化的对象(如未实现
的自定义类、线程局部变量、临时IO句柄等)做特殊处理,直接抛异常或跳过
数据库中对应的
或
表必须成功写入,否则挂起事务回滚
需显式控制的三类变量序列化行为
不同作用域的变量,其序列化方式和影响范围不同,开发者需按需干预:
全局变量(Global)
:绑定到流程实例,跨所有子执行和任务可见。挂起时默认全量序列化,适合存业务主键、审批状态等共享数据
局部变量(Local)
:仅绑定到特定任务或执行,挂起时独立序列化。适合存临时计算结果、用户输入草稿等隔离数据
外部传入变量
:如启动流程时通过
传入的对象。必须确保其类型可被引擎序列化器识别(如Java的
、
、标准集合、或已注册的自定义类)
避免序列化失败的实操要点
常见挂起失败,80%源于变量序列化环节。以下做法可大幅降低风险:
禁用不可序列化对象:不把
、
、Lambda表达式、匿名内部类实例等塞进变量
自定义类加
,并显式定义
,防止版本升级后反序列化失败
敏感字段用
修饰,避免被持久化(如密码、token)
大对象(如Base64图片、大JSON字符串)建议只存URL或ID,而非原始内容,减少序列化开销与存储压力
挂起后变量状态的验证方法
不能只依赖日志说“挂起成功”,要主动确认变量是否真实落库:
查数据库表:
用历史服务查询:
激活前先调用
,确认关键变量存在且值正确
SerializableACT_RU_VARIABLEACT_HI_VARINSTstartProcessInstanceByKey(key, variables)StringIntegerHttpServletRequestConnectionimplements SerializableserialVersionUIDtransientSELECT * FROM ACT_RU_VARIABLE WHERE EXECUTION_ID_ = 'xxx' OR TASK_ID_ = 'xxx'historyService.createHistoricVariableInstanceQuery().processInstanceId("xxx").list()runtimeService.getVariables(processInstanceId)