bpmn & spiffworkflow python bpmn流程引擎的学习

2,788 阅读2分钟

最近在做框架的工作流集成,基于django+vue的平台,查了很多资料,python并没有像java那边有flowable,Activiti这样的工作流引擎,技术选型了很久最终选择了spiffworkflow这个包,基于python,发展了10来年的库,功能也很完善了,加上我们自己的web功能,后期可以做成python,django开源的开源工作流引擎

这是我们框架的地址:(dvadmin)gitee.com/liqianglog/… 欢迎star

Bpmn知识点

1.bpmn文件格式可以为xml bpmn两种

2.bpmn xml根节点为 bpmn:definitions 包含一个bpmn:process节点,里面包含了数据节点的描述,还有一个bpmn:BPMNDiagram节点,这个是可视化节点的坐标信息,在给流程引擎解析xml时候可以没有这个节点,这个节点主要是在bpmn可视化建模软件里绘图时候用到的坐标信息,相当于是给人看的,流程引擎解析流程并不需要这个节点

image-20221204230757998

Spiffworkflow学习

1.启动一个工作流流程的步骤如下

  • step1:首先得创建一个WorkflowSpec对象,这个实例表示工作流的定义
  • Step2:创建一个Workflow对象,这个实例表示工作流的建模,我们需要拿到这个实例来做一些操作

实例代码:新建一个bpmnworkflow

 def parse_workflow(parser, process, bpmn_files, dmn_files=None, load_all=True):
     """
     解析workflow 返回BpmnWorkflow对象
     """
     # parser.add_bpmn_files(bpmn_files)
     parser.add_bpmn_xml(bpmn_files)
     if dmn_files:
         parser.add_dmn_files(dmn_files)
     top_level = parser.get_spec(process)
     if load_all:
         subprocesses = parser.find_all_specs()
     else:
         subprocesses = parser.get_subprocess_specs(process)
     return BpmnWorkflow(top_level, subprocesses, script_engine=PythonScriptEngine(scripting_additions={}))
 ​
 ​

parser.add_bpmn_files是解析一个标准的bpmn2.0xml文件对象

parser.add_bpmn_xml是解析标准的bpmn xml 字符串对象

启动流程

 def run(workflow):
     """
     启动流程
     """
     start_event = workflow.get_tasks_from_spec_name("Start")
     TASK_HANDLERS.get(StartEvent)(start_event)
 ​
     while not workflow.is_completed():
         all_tasks = workflow.get_tasks()
 ​
         for task in all_tasks:
             # print(task.task_spec.name)
             handler = TASK_HANDLERS.get(type(task.task_spec))
             if handler is not None:
                 handler(task)
 ​
         workflow.refresh_waiting_tasks()
         workflow.do_engine_steps()
 ​
     end_event = workflow.get_tasks_from_spec_name("End")
     TASK_HANDLERS.get(EndEvent)(end_event)

可以根据workflow对象拿到具体的task,比如read_tasks 开始事件start_event结束事件end_event

自定义scriptEngine,适用场景:对应scriptTask,serviceTask,在bpmn文件中调用定义好的变量,函数等

 class DvflowScriptEngine(PythonScriptEngine):
     def call_service(self, operation_name, operation_params, task_data):
         print(f'call service {operation_name}, {operation_params}')
 ​
         data_dict = {
             'code': 200,
             'msg': 'test is ok'
         }
         return json.dumps(data_dict)
 SCRIPT_ADDITIONS = {
     'script_engine_callback_event': script_engine_callback_event,
 }
 def parse_workflow(parser, process, bpmn_files, dmn_files=None, load_all=True):
     """
     解析workflow 返回BpmnWorkflow对象
     """
     # parser.add_bpmn_files(bpmn_files)
     parser.add_bpmn_xml(bpmn_files)
     if dmn_files:
         parser.add_dmn_files(dmn_files)
     top_level = parser.get_spec(process)
     if load_all:
         subprocesses = parser.find_all_specs()
     else:
         subprocesses = parser.get_subprocess_specs(process)
     return BpmnWorkflow(top_level, subprocesses, script_engine=DvflowScriptEngine(scripting_additions=SCRIPT_ADDITIONS))

这里返回的BpmnWorkflow对象里的script_engine参数对应上面我们自定义的scriptEngine,这样script_additions的映射关系就添加到了系统里,我们可以在bpmn文件里调用这个script_engine_callback_event