Skip to content

poseidon项目flowable模块

muggle edited this page Apr 11, 2019 · 12 revisions

flowable官方文档 里面介绍很全面

其中包括: 1.bpmn2.0的结构;

2.flowable的使用;

3.flowable在spring中的使用;

4.flowable在springboot中的使用

如果你想使用flowable ,那么这是最好的参考资料。

flowable 对springboot的集成很高,只要引入它的starter就行,所有配置都是自动化的,(制作springboot的starter教程)数据源,事物这些都不用你配置,如果你引入其rest-api模块,连controller层都不用你写,就是这么贴心。

我们知道流程总是伴随着业务逻辑的,flowable只对流程进行管控,对业务逻辑不去管,由程序员自己去实现每一个流程该做哪些事情,做到了很好的解耦和职责的分离,那么flowable是怎么做到的呢?答案是通过bpmn文件和监听器。bpmn(或.bpmn20.xml)文件定义了工作流的步骤,flowable去加载这个bpmn然后解析出对应的步骤,在bpmn中我们可以指定每个步骤对应的监听器,当流程触发的时候监听器的代码就会被执行。作为开发人员,只要写好xml和业务代码就行,流程交给flowable去管理。

具体使用细节请参看手册

flowable 表结构 -3.7章

全局监听器,流程定义监听器,事件监听器,任务监听器-3.18章 -8.5章

使用flowable的主注意事项 flowable常用节点xml解析

userTask 代表用户任务

sequenceFlow 代表线条

serviceTask 自动调用任务

exclusiveGateway 排他网关 通过其conditionExpression 节点的表达式来判断走哪条线

在springboot中默认流程定义文件后缀 为.bpmn或者.bpmn20.xml且指定的文件夹名称为proceses 部署一个流程只需编写xml,和监听器,然后将xml放到对应位置,注册监听器即可

注意

在xml中使用形如 flowable:class="com.xxx.Listener.TransferListener"的表达式 会根据反射new 一个实例,

使用形如 flowable:delegateExpression="${transNotAppoveListener}" 的表达式则会从spring容器中根据名称拿到对应的bean

下面贴出flowable的一个流程示例对应的xml及流程图:

<?xml version="1.0" encoding="UTF-8"?>
<definitions
        xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
        xmlns:flowable="http://flowable.org/bpmn"
        targetNamespace="Examples">

    <process id="transfer_all"  isExecutable="true" name="调拨单流程定义">
        <startEvent id="trans_start" name="开启调度流程" >
            <extensionElements>
                <flowable:executionListener event="end" delegateExpression="${transFerStartListener}"/>
            </extensionElements>
        </startEvent>
        <exclusiveGateway id="bool_auto_audit" name="是否自动审核"/>
        <sequenceFlow sourceRef="trans_start" targetRef="bool_auto_audit"/>
        <userTask id="trans_user_audit" name="审核人审核订单" flowable:assignee="${assignee}">
            <extensionElements>
                <flowable:taskListener event="complete"  delegateExpression="${userTaskTransListener}"/>
            </extensionElements>
        </userTask>
        <sequenceFlow sourceRef="bool_auto_audit" targetRef="trans_user_audit">
            <conditionExpression >
                <![CDATA[${!autoAudit}]]>
            </conditionExpression>
        </sequenceFlow>
        <serviceTask id="trans_auto_audit" name="自动审核订单" flowable:delegateExpression="${transAutoAuditListener}"/>
        <sequenceFlow sourceRef="bool_auto_audit" targetRef="trans_auto_audit">
            <conditionExpression >
                <![CDATA[${autoAudit}]]>
            </conditionExpression>
        </sequenceFlow>
        <exclusiveGateway id="bool_access" name="是否通过审核,是否生成入库单"/>
        <sequenceFlow sourceRef="trans_auto_audit" targetRef="bool_access"/>
        <sequenceFlow sourceRef="trans_user_audit" targetRef="bool_access"/>
        <serviceTask id="trans_not_approve"  name="流程不通过审核相关操作"  flowable:delegateExpression="${transNotAppoveListener}"/>
        <sequenceFlow sourceRef="bool_access" targetRef="trans_not_approve">
            <conditionExpression >
                <![CDATA[${!approved}]]>
            </conditionExpression>
        </sequenceFlow>


        <userTask id="trans_user_into" name="手动生成调拨入库单" flowable:assignee="${assignee}">
            <extensionElements>
                <flowable:taskListener event="complete"  delegateExpression="${transIntoListener}"/>
            </extensionElements>
        </userTask>
        <sequenceFlow sourceRef="bool_access" targetRef="trans_user_into">
            <conditionExpression >
                <![CDATA[${approved&&!autoInto}]]>
            </conditionExpression>
        </sequenceFlow>
        <serviceTask id="trans_auto_into" name="自动生成调拨入库单"  flowable:delegateExpression="${transAutoIntoListener}"/>
        <sequenceFlow sourceRef="bool_access" targetRef="trans_auto_into">
            <conditionExpression >
                <![CDATA[${approved&&autoInto}]]>
            </conditionExpression>
        </sequenceFlow>
        <endEvent id="end_trans" name="流程结束"/>
        <sequenceFlow sourceRef="trans_not_approve" targetRef="end_trans"/>
        <sequenceFlow sourceRef="trans_user_into" targetRef="end_trans"/>
        <sequenceFlow sourceRef="trans_auto_into" targetRef="end_trans"/>
    </process>

</definitions>
          开始
           |
        是否自动审核
      |             |
      是            否
      |             |    
     手动审核      自动审核
       |            |
       —————————————
             |
   是否通过审核,是否自动生成入库单
 |             |               |
 未通过      通过,不生成    通过生成
  |            |               |
  |           手动生成         自动生成
  |            |                |
   ——————————————————————————————
               |
              结束

然后在spring容器中注册对应的监听器

@Component(value = "transAutoAuditListener")
public class TransAutoAuditListener implements JavaDelegate {
    @Autowired
    TestService testService;
    @Override
    public void execute(DelegateExecution delegateExecution) {
        testService.test(delegateExecution.getVariables());
    }
}

@Component(value = "transAutoIntoListener")
public class TransAutoIntoListener implements JavaDelegate {
    @Autowired
    TestService testService;
    @Override
    public void execute(DelegateExecution delegateExecution) {
        testService.test(delegateExecution.getVariables());
    }
}

@Component(value = "transFerStartListener")
public class TransFerStartListener implements ExecutionListener {
    @Autowired
    TestService testService;
    @Override
    public void notify(DelegateExecution delegateExecution) {
        Map<String, Object> variables = delegateExecution.getVariables();
//        Map<String, VariableInstance> variableInstances = delegateExecution.getVariableInstances();
        testService.test(variables);
    }
}

@Component(value = "transIntoListener")
public class TransIntoListener implements TaskListener {
    @Autowired
    TestService testService;
    @Override
    public void notify(DelegateTask delegateTask) {
        testService.test(delegateTask.getVariables());
        System.out.println(delegateTask.getVariableInstances());
    }
}

@Component(value = "transNotAppoveListener")
public class TransNotAppoveListener implements JavaDelegate {
    @Autowired
    TestService testService;

    @Override
    public void execute(DelegateExecution delegateExecution) {
        testService.test(delegateExecution.getVariables());
        Map<String, Object> variables = delegateExecution.getVariables();
//        Map<String, VariableInstance> variableInstances = delegateExecution.getVariableInstances();
        System.out.println(variables);
    }
}

@Component(value = "userTaskTransListener")
public class UserTaskTransListener implements TaskListener {
    @Autowired
    TestService testService;
    @Override
    public void notify(DelegateTask delegateTask) {
        Map<String, VariableInstance> variableInstances = delegateTask.getVariableInstances();
        System.out.println();
    }
}

更多使用细节参看项目的flowable代码 (很多人在使用工作流时,通过工作流提供的service去手动推送流程,然后同时执行自己代码,这种方式是错误的)

想要使用好工作流,建议手写bpmn20.xml文件,而不是使用一些绘图工具来生成。