您的位置:首页 > 其它

Flowable工作流

Z_xiansheng11 2020-07-21 04:15 190 查看 https://blog.csdn.net/z_xiansh

Flowable工作流

Flowable工作流

  • 二.flowable实例
  • 三.flowable数据库表的介绍
  • 四.flowable中的五个引擎
  • 一.认识flowable

    Flowable是一个使用Java编写的轻量级业务流程引擎。Flowable流程引擎让你可以部署BPMN 2.0流程定义(用于定义流程的行业XML标准)、创建这些流程定义的流程实例、进行查询、访问运行中或历史的流程实例与相关数据,等等。

    1.flowable发展史

    三个框架诞生的先后顺序是 JBPM>Activiti>Flowable
    2010年,JBPM4发布之后, Joram Barrez(JBPM的创始人)与合作伙伴在JBPM的未来架构上产生了重大的分歧,于是乎Tom Baeyens离开了JBoss公司并加入到Alfresco公司,真是一言不合就“分手”。
    2010年6月18日,Alfresco公司发布了第一个Activiti版本(5.0.alpha1)。Activiti直接将第一个版本号定义为5.0可谓意味深远,表明Activiti框架才是JBPM4的延续。从上面的图可以看出来,activiti从12年底的时候,才开始大量的重构和开发。
    2010年10月6日,JBoss完全抛弃了JBPM4的架构设计,使用了规则引擎(Drools Flow)进行项目的彻底重构,并推出了JBPM5。
    2016年10月13日,Tijs Rademarkers (原Activiti Project Lead)发布了Flowable 5.22.0版本的上线公告,该版本基于上Activiti5.22版本拉取的新分支,并没有从本质上增加更多的新特性。
    2016年11月1日,Flowable团队开放了Flowable Eclipse Designer(该插件用于在Eclipse开发工具中绘制流程文档)。
    2016年12月15日,Flowable团队发布了Flowable 6.0.0.RC1版本的上线公告。
    2017年3月27日,Flowable团队发布了Flowable 5.23.0版本的上线公告。
    2017年4月28日,Flowable团队发布了Flowable 6.0.1版本的上线公告。
    2017年5月29日,大名鼎鼎的Joram Barrez(原JBPM的创始人)加入了Flowable团队,专心于Flowable的研发。
    2017年7月21日,Flowable团队发布了Flowable 6.1.1版本的上线公告。
    2017年10月13日,Flowable团队发布了flowable-6.2.0-release版本的上线公告。
    2017年12月11日,Flowable团队发布了flowable-6.2.1-release版本的上线公告。
    2018年04月04日,Flowable团队发布了flowable-6.3.0-release版本的上线公告。
    2018年05月22日,Flowable团队发布了flowable-6.3.1-release版本的上线公告。
    2018年10月02日,Flowable团队发布了flowable-6.4.0-release版本的上线公告。

    官网:https://www.flowable.org/

    中文文档:https://tkjohn.github.io/flowable-userguide/#_configuration

    2.BPMN


    BPMN 标准发展版本历史如下。BPMN2.0在1.x基础上新增了元模型、存储、交互、执行。

    BPMN2.0概述:

    1、是一套业务流程模型与符号建模标准;

    2、精准的执行语义来描述元素的操作,可以将元素的操作描述的很清楚,没有二义性;

    3、以XML为载体,以符号可视化业务,每个xml模块都可以对应符号,流程图与xml有一个相互转换的过程。

    BPMN2.0所包含的元素:

    1、流对象(FlowObjects):包括其中的活动、事件与网关。

    活动(Activities)  [User Task 、Service Task ......]
    
    事件(Events)  [Start Event、End Event......]
    
    网关(Gateways)  [Exclusive Gateway ......]

    2、连接对象(ConnectingObject):流对象通过连接对象连接起来表示数据的流转;

    3、数据(Data):包括一些数据对象、数据输入\输出对象等。

    数据对象(Data Objects)
    
    数据输入(Data Inputs )
    
    数据输出(Data OutPuts)
    
    数据存储(Data Stores)

    4、泳道(Swimlanes):对业务做范围维度的区分,一般通过不同的职能进行区分。

    ​ 池(Pools ): 池描述流程中的一个参与者。可以看做是将一系列活动区别于其他池的一个图形容器

    ​ 道(Lanes ):道就是在池里面再细分,可以是垂直的也可以是水平的。道也是用于组织和分类活动。

    5、描述对象(Artifacts):不影响流程运行,为流程图可读性进行补充性描述。

    一个简单的流程图

    二.flowable实例

    项目结构如下:

    1.导入依赖

    <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.0.5.RELEASE</version>
    <relativePath />
    </parent>
    <dependencies>
    <!--flowable-->
    <dependency>
    <groupId>org.flowable</groupId>
    <artifactId>flowable-spring-boot-starter</artifactId>
    <version>6.4.0</version>
    </dependency>
    <!--数据库-->
    <dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.45</version>
    </dependency>
    <!--rest支持-->
    <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    </dependencies>

    2.编写启动类

    @SpringBootApplication
    public class RepairApp {
    /**
    *日志信息
    */
    private static final Logger log = LoggerFactory.getLogger(RepairApp.class);
    
    public static void main(String[] args) {
    log.info("项目开始启动");
    SpringApplication.run(RepairApp.class,args);
    log.info("项目启动完成");
    }
    }

    3.配置文件

    #数据源配置
    spring:
    datasource:
    url: jdbc:mysql://106.13.61.208/repair?characterEncoding=UTF-8
    username: root
    password: 123456
    
    #flowable配置
    #自动部署验证设置:true-开启(默认)、false-关闭
    flowable:
    check-process-definitions: false

    4.导入BPMN文件

    <?xml version="1.0" encoding="UTF-8"?>
    <definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:flowable="http://flowable.org/bpmn" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC" xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI" typeLanguage="http://www.w3.org/2001/XMLSchema" expressionLanguage="http://www.w3.org/1999/XPath" targetNamespace="http://www.flowable.org/processdef">
    <process id="mydemo" name="demo" isExecutable="true">
    <documentation>111</documentation>
    <startEvent id="startEvent1"></startEvent>
    <userTask id="sid-7C91C99C-1D01-4AC6-88FB-03CAA1603477" name="出差报销" flowable:assignee="${user}">
    <extensionElements>
    <modeler:initiator-can-complete xmlns:modeler="http://flowable.org/modeler"><![CDATA[false]]></modeler:initiator-can-complete>
    </extensionElements>
    </userTask>
    <exclusiveGateway id="sid-49E6AEBB-D5B9-4B9E-A99E-2E2454642891"></exclusiveGateway>
    <sequenceFlow id="sid-5B89E7D6-7B3A-439A-9F15-D3B985515C7E" sourceRef="sid-7C91C99C-1D01-4AC6-88FB-03CAA1603477" targetRef="sid-49E6AEBB-D5B9-4B9E-A99E-2E2454642891"></sequenceFlow>
    <userTask id="sid-457C6876-FE69-47E8-B9B1-5F1AEC979758" name="经理审批" flowable:assignee="manage">
    <extensionElements>
    <modeler:initiator-can-complete xmlns:modeler="http://flowable.org/modeler"><![CDATA[false]]></modeler:initiator-can-complete>
    </extensionElements>
    </userTask>
    <userTask id="sid-05C7AEC3-C967-4056-9AAA-B21C57E214F4" name="老板审批" flowable:assignee="boss">
    <extensionElements>
    <modeler:initiator-can-complete xmlns:modeler="http://flowable.org/modeler"><![CDATA[false]]></modeler:initiator-can-complete>
    </extensionElements>
    </userTask>
    <endEvent id="sid-27C7BF58-F8CF-4B3A-868C-F2158DF03AD8"></endEvent>
    <sequenceFlow id="sid-1A2DAF03-7BA0-4531-A02D-09F6AF31C33B" sourceRef="startEvent1" targetRef="sid-7C91C99C-1D01-4AC6-88FB-03CAA1603477"></sequenceFlow>
    <sequenceFlow id="sid-C2FEB1B6-B383-41AF-BBA8-CC9CCB4FD2FA" name="驳回" sourceRef="sid-457C6876-FE69-47E8-B9B1-5F1AEC979758" targetRef="sid-7C91C99C-1D01-4AC6-88FB-03CAA1603477">
    <conditionExpression xsi:type="tFormalExpression"><![CDATA[${outcome=="驳回"}]]></conditionExpression>
    </sequenceFlow>
    <sequenceFlow id="sid-5D877DFD-FD4F-4686-AD25-162AF7265D28" name="驳回" sourceRef="sid-05C7AEC3-C967-4056-9AAA-B21C57E214F4" targetRef="sid-7C91C99C-1D01-4AC6-88FB-03CAA1603477">
    <conditionExpression xsi:type="tFormalExpression"><![CDATA[${outcome=="驳回"}]]></conditionExpression>
    </sequenceFlow>
    <sequenceFlow id="sid-A4FA12EE-2B6E-40E1-8324-7C3D08C59D19" name="money&lt;=500" sourceRef="sid-49E6AEBB-D5B9-4B9E-A99E-2E2454642891" targetRef="sid-457C6876-FE69-47E8-B9B1-5F1AEC979758">
    <conditionExpression xsi:type="tFormalExpression"><![CDATA[${money<=500}]]></conditionExpression>
    </sequenceFlow>
    <sequenceFlow id="sid-0EFF9C10-9F5B-45C8-B0D5-DF9C6FA3466C" name="通过" sourceRef="sid-05C7AEC3-C967-4056-9AAA-B21C57E214F4" targetRef="sid-27C7BF58-F8CF-4B3A-868C-F2158DF03AD8">
    <conditionExpression xsi:type="tFormalExpression"><![CDATA[${outcome=="通过"}]]></conditionExpression>
    </sequenceFlow>
    <sequenceFlow id="sid-73F869E4-1EEF-4218-B568-E431EC21D1DA" name="通过" sourceRef="sid-457C6876-FE69-47E8-B9B1-5F1AEC979758" targetRef="sid-27C7BF58-F8CF-4B3A-868C-F2158DF03AD8">
    <conditionExpression xsi:type="tFormalExpression"><![CDATA[${outcome=="通过"}]]></conditionExpression>
    </sequenceFlow>
    <sequenceFlow id="sid-218819A2-D9B3-4EAC-858D-A1F12D9DDBFF" name="money&gt;500" sourceRef="sid-49E6AEBB-D5B9-4B9E-A99E-2E2454642891" targetRef="sid-05C7AEC3-C967-4056-9AAA-B21C57E214F4">
    <conditionExpression xsi:type="tFormalExpression"><![CDATA[${money>500}]]></conditionExpression>
    </sequenceFlow>
    </process>
    <bpmndi:BPMNDiagram id="BPMNDiagram_mydemo">
    <bpmndi:BPMNPlane bpmnElement="mydemo" id="BPMNPlane_mydemo">
    <bpmndi:BPMNShape bpmnElement="startEvent1" id="BPMNShape_startEvent1">
    <omgdc:Bounds height="30.0" width="30.0" x="60.0" y="199.0"></omgdc:Bounds>
    </bpmndi:BPMNShape>
    <bpmndi:BPMNShape bpmnElement="sid-7C91C99C-1D01-4AC6-88FB-03CAA1603477" id="BPMNShape_sid-7C91C99C-1D01-4AC6-88FB-03CAA1603477">
    <omgdc:Bounds height="80.0" width="100.0" x="158.0" y="174.0"></omgdc:Bounds>
    </bpmndi:BPMNShape>
    <bpmndi:BPMNShape bpmnElement="sid-49E6AEBB-D5B9-4B9E-A99E-2E2454642891" id="BPMNShape_sid-49E6AEBB-D5B9-4B9E-A99E-2E2454642891">
    <omgdc:Bounds height="40.0" width="40.0" x="303.0" y="194.0"></omgdc:Bounds>
    </bpmndi:BPMNShape>
    <bpmndi:BPMNShape bpmnElement="sid-457C6876-FE69-47E8-B9B1-5F1AEC979758" id="BPMNShape_sid-457C6876-FE69-47E8-B9B1-5F1AEC979758">
    <omgdc:Bounds height="80.0" width="100.0" x="405.0" y="174.0"></omgdc:Bounds>
    </bpmndi:BPMNShape>
    <bpmndi:BPMNShape bpmnElement="sid-05C7AEC3-C967-4056-9AAA-B21C57E214F4" id="BPMNShape_sid-05C7AEC3-C967-4056-9AAA-B21C57E214F4">
    <omgdc:Bounds height="80.0" width="100.0" x="273.0" y="295.0"></omgdc:Bounds>
    </bpmndi:BPMNShape>
    <bpmndi:BPMNShape bpmnElement="sid-27C7BF58-F8CF-4B3A-868C-F2158DF03AD8" id="BPMNShape_sid-27C7BF58-F8CF-4B3A-868C-F2158DF03AD8">
    <omgdc:Bounds height="28.0" width="28.0" x="441.0" y="321.0"></omgdc:Bounds>
    </bpmndi:BPMNShape>
    <bpmndi:BPMNEdge bpmnElement="sid-5B89E7D6-7B3A-439A-9F15-D3B985515C7E" id="BPMNEdge_sid-5B89E7D6-7B3A-439A-9F15-D3B985515C7E">
    <omgdi:waypoint x="257.9499999999977" y="214.21623376623376"></omgdi:waypoint>
    <omgdi:waypoint x="303.4130434782609" y="214.4130434782609"></omgdi:waypoint>
    </bpmndi:BPMNEdge>
    <bpmndi:BPMNEdge bpmnElement="sid-C2FEB1B6-B383-41AF-BBA8-CC9CCB4FD2FA" id="BPMNEdge_sid-C2FEB1B6-B383-41AF-BBA8-CC9CCB4FD2FA">
    <omgdi:waypoint x="455.0" y="174.0"></omgdi:waypoint>
    <omgdi:waypoint x="455.0" y="135.0"></omgdi:waypoint>
    <omgdi:waypoint x="204.20703124999994" y="135.0"></omgdi:waypoint>
    <omgdi:waypoint x="204.20703124999994" y="174.0"></omgdi:waypoint>
    </bpmndi:BPMNEdge>
    <bpmndi:BPMNEdge bpmnElement="sid-0EFF9C10-9F5B-45C8-B0D5-DF9C6FA3466C" id="BPMNEdge_sid-0EFF9C10-9F5B-45C8-B0D5-DF9C6FA3466C">
    <omgdi:waypoint x="372.95000000000005" y="335.0"></omgdi:waypoint>
    <omgdi:waypoint x="441.0" y="335.0"></omgdi:waypoint>
    </bpmndi:BPMNEdge>
    <bpmndi:BPMNEdge bpmnElement="sid-A4FA12EE-2B6E-40E1-8324-7C3D08C59D19" id="BPMNEdge_sid-A4FA12EE-2B6E-40E1-8324-7C3D08C59D19">
    <omgdi:waypoint x="342.51504576659045" y="214.42748091603053"></omgdi:waypoint>
    <omgdi:waypoint x="404.99999999999324" y="214.18992395437263"></omgdi:waypoint>
    </bpmndi:BPMNEdge>
    <bpmndi:BPMNEdge bpmnElement="sid-1A2DAF03-7BA0-4531-A02D-09F6AF31C33B" id="BPMNEdge_sid-1A2DAF03-7BA0-4531-A02D-09F6AF31C33B">
    <omgdi:waypoint x="89.94999896690354" y="214.0"></omgdi:waypoint>
    <omgdi:waypoint x="157.99999999997266" y="214.0"></omgdi:waypoint>
    </bpmndi:BPMNEdge>
    <bpmndi:BPMNEdge bpmnElement="sid-5D877DFD-FD4F-4686-AD25-162AF7265D28" id="BPMNEdge_sid-5D877DFD-FD4F-4686-AD25-162AF7265D28">
    <omgdi:waypoint x="273.0" y="335.0"></omgdi:waypoint>
    <omgdi:waypoint x="208.0" y="335.0"></omgdi:waypoint>
    <omgdi:waypoint x="208.0" y="253.95000000000002"></omgdi:waypoint>
    </bpmndi:BPMNEdge>
    <bpmndi:BPMNEdge bpmnElement="sid-218819A2-D9B3-4EAC-858D-A1F12D9DDBFF" id="BPMNEdge_sid-218819A2-D9B3-4EAC-858D-A1F12D9DDBFF">
    <omgdi:waypoint x="323.42083333333335" y="233.52100333055787"></omgdi:waypoint>
    <omgdi:waypoint x="323.1657676348548" y="295.0"></omgdi:waypoint>
    </bpmndi:BPMNEdge>
    <bpmndi:BPMNEdge bpmnElement="sid-73F869E4-1EEF-4218-B568-E431EC21D1DA" id="BPMNEdge_sid-73F869E4-1EEF-4218-B568-E431EC21D1DA">
    <omgdi:waypoint x="455.0" y="253.95000000000002"></omgdi:waypoint>
    <omgdi:waypoint x="455.0" y="321.0"></omgdi:waypoint>
    </bpmndi:BPMNEdge>
    </bpmndi:BPMNPlane>
    </bpmndi:BPMNDiagram>
    </definitions>

    5.部署流程
    service层

    /**
    * 部署流程
    * filePath 文件路径 name 流程名字
    */
    public Map<String, Object> deploymentFlow(String filePath, String name) {
    try {
    DeploymentBuilder deploymentBuilder = repositoryService.createDeployment()
    .addClasspathResource(filePath).name(name);
    Deployment deployment = deploymentBuilder.deploy();
    logger.info("成功:部署工作流程:" + filePath);
    logger.error("deployment.getKey():" + deployment.getKey());
    logger.error("deployment.getName():" + deployment.getName());
    //acr_re_deployment表的id
    String id = deployment.getId();
    
    ProcessDefinitionQuery query = repositoryService.createProcessDefinitionQuery();
    //搜索条件deploymentId
    query.deploymentId(id);
    //最新版本过滤
    query.latestVersion();
    //查询
    ProcessDefinition definition = query.singleResult();
    //act_re_procdef表的key
    String key = definition.getKey();
    System.out.println("act_re_procdef表的key" + key);
    String id1 = definition.getId();
    System.out.println("流程定义id1:::" + id1);
    
    Map<String, Object> map = new HashMap<>();
    map.put("act_re_procdef表的key", key);
    map.put("act_re_procdef表的id", id1);
    return map;
    } catch (Exception e) {
    logger.error("失败:部署工作流:" + e);
    return null;
    }
    }

    controller层:

    /**
    * 部署流程
    * */
    @RequestMapping("/deploy")
    public Map<String,Object> deploymentFlow(String filePath, String name){
    return flowableService.deploymentFlow(filePath,name);
    }

    测试:http://127.0.0.1:8080/deploy?filePath=processes/demo.bpmn20.xml

    6.启动流程
    service层:

    /**
    * 开始流程
    */
    public ProcessInstance startProcessInstance(String processKey, Map map) {
    // 定义流程的key
    // String processDefinitionKey = processKey;
    if (StringUtils.isEmpty(processKey)) {
    return null;
    }
    ProcessInstance pi = runtimeService.startProcessInstanceByKey(processKey, map);
    
    System.out.println("processInstanceId流程实例ID:" + pi.getId());
    System.out.println("ProcessDefinitionId流程定义ID:" + pi.getProcessDefinitionId());
    return pi;
    }

    controller层:

    /**
    * 启动流程
    * */
    @RequestMapping("/start")
    public Map<String, Object> startProcessInstance(String processKey, String userId){
    Map<String, Object> map = new HashMap<>();
    map.put("user",userId);
    ProcessInstance pi = flowableService.startProcessInstance(processKey, map);
    Map<String, Object> pra = new HashMap<>();
    pra.put("流程实例ID", pi.getId());
    pra.put("流程定义ID:", pi.getProcessDefinitionId());
    return pra;
    }

    测试:http://127.0.0.1:8080/start?processKey=mydemo&userId=123


    7.查看待办任务
    service层:

    /**
    * 查询代理人任务
    */
    public List<Task> queryAssigneeTask(String assignee) {
    List<Task> tasks = taskService.createTaskQuery().taskAssignee(assignee).list();
    return tasks;
    }

    controler层:

    /**
    * 查询代理人任务
    * */
    @RequestMapping("/queryTask")
    public Map<String, Object> queryAssigneeTask(String assignee){
    List<Task> tasks=flowableService.queryAssigneeTask(assignee);
    Map<String, Object> map = new HashMap<>();
    int i = 1 ;
    for (Task task : tasks) {
    map.put("task"+i,task.toString());
    i++;
    }
    return map;
    }

    测试:http://127.0.0.1:8080/queryTask?assignee=123


    id:待办理的任务节点id

    name:待办理的任务的描述

    8.出差报销
    service层:

    /**
    * 完成任务
    */
    public boolean completeTask(String taskId, Map<String, Object> paras) {
    
    Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
    if (task == null) {
    logger.error("task:" + task);
    return false;
    }
    
    if (null == paras) {
    taskService.complete(taskId);
    } else {
    taskService.complete(taskId, paras);
    }
    
    return true;
    }

    controller层:

    /**
    * 出差报销
    */
    @RequestMapping("reimburse")
    public String reimburse(String taskId, Integer money) {
    Map<String, Object> map = new HashMap<>();
    map.put("money", money);
    try {
    flowableService.completeTask(taskId, map);
    } catch (Exception e) {
    e.printStackTrace();
    return "系统异常";
    }
    return "申请报销";
    }

    测试:http://127.0.0.1:8080/reimburse?taskId=5af07084-ccbe-11e9-80cb-1ae3475a33dc&money=600

    9.审核通过
    service层:同上

    /**
    * 完成任务
    */
    public boolean completeTask(String taskId, Map<String, Object> paras) {
    
    Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
    if (task == null) {
    logger.error("task:" + task);
    return false;
    }
    
    if (null == paras) {
    taskService.complete(taskId);
    } else {
    taskService.complete(taskId, paras);
    }
    
    return true;
    }

    controller层

    /**
    * 审核通过
    * */
    @RequestMapping("/pass")
    public String pass(String taskId){
    Map<String, Object> map = new HashMap<>();
    map.put("outcome", "通过");
    try {
    flowableService.completeTask(taskId, map);
    }catch (Exception e){
    e.printStackTrace();
    return "系统异常";
    }
    return "审核通过";
    }

    测试:http://127.0.0.1:8080/pass?taskId=90a3e272-ccbf-11e9-823f-1ae3475a33dc

    10.查看流程图
    service层:

    /**
    * 查看流程是否完成
    */
    public boolean isFinished(String processInstanceId) {
    return historyService.createHistoricProcessInstanceQuery().finished()
    .processInstanceId(processInstanceId).count() > 0;
    }
    
    /**
    * 查看流程图
    */
    public void genProcessDiagram(HttpServletResponse httpServletResponse, String processId) {
    /**
    * 获得当前活动的节点
    */
    String processDefinitionId = "";
    if (this.isFinished(processId)) {
    // 如果流程已经结束,则得到结束节点
    HistoricProcessInstance pi = historyService.createHistoricProcessInstanceQuery().processInstanceId(processId).singleResult();
    
    processDefinitionId = pi.getProcessDefinitionId();
    } else {
    // 如果流程没有结束,则取当前活动节点
    // 根据流程实例ID获得当前处于活动状态的ActivityId合集
    ProcessInstance pi = runtimeService.createProcessInstanceQuery().processInstanceId(processId).singleResult();
    processDefinitionId = pi.getProcessDefinitionId();
    }
    List<String> highLightedActivitis = new ArrayList<String>();
    
    /**
    * 获得活动的节点
    */
    List<HistoricActivityInstance> highLightedActivitList = historyService.createHistoricActivityInstanceQuery().processInstanceId(processId).orderByHistoricActivityInstanceStartTime().asc().list();
    
    for (HistoricActivityInstance tempActivity : highLightedActivitList) {
    String activityId = tempActivity.getActivityId();
    highLightedActivitis.add(activityId);
    }
    
    List<String> flows = new ArrayList<>();
    
    ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    //获取流程图
    BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId);
    ProcessEngineConfiguration engconf = processEngine.getProcessEngineConfiguration();
    
    ProcessDiagramGenerator diagramGenerator = engconf.getProcessDiagramGenerator();
    InputStream in = diagramGenerator.generateDiagram(bpmnModel, "bmp", highLightedActivitis, flows, engconf.getActivityFontName(),
    engconf.getLabelFontName(), engconf.getAnnotationFontName(), engconf.getClassLoader(), 1.0, true);
    OutputStream out = null;
    byte[] buf = new byte[1024];
    int legth = 0;
    try {
    out = httpServletResponse.getOutputStream();
    while ((legth = in.read(buf)) != -1) {
    out.write(buf, 0, legth);
    }
    } catch (IOException e) {
    logger.error("操作异常", e);
    } finally {
    try {
    if (out != null) {
    out.close();
    }
    if (in != null) {
    in.close();
    }
    } catch (IOException e) {
    e.printStackTrace();
    }
    }
    }

    controller层:

    /**
    * 查看流程图
    */
    @RequestMapping("/processDiagram")
    public void genProcessDiagram(HttpServletResponse httpServletResponse, String processId) throws Exception {
    flowableService.genProcessDiagram(httpServletResponse, processId);
    }

    测试:http://127.0.0.1:8080/processDiagram?processId=5ae6fa9f-ccbe-11e9-80cb-1ae3475a33dc

    问题:流程图中中文有乱码

    解决:添加配置类

    @Configuration
    public class Config implements EngineConfigurationConfigurer<SpringProcessEngineConfiguration>{
    @Override
    public void configure(SpringProcessEngineConfiguration engineConfiguration) {
    engineConfiguration.setActivityFontName("宋体");
    engineConfiguration.setLabelFontName("宋体");
    engineConfiguration.setAnnotationFontName("宋体");
    }
    }

    重启项目,再次访问
    乱码问题解决!!!

    三.flowable数据库表的介绍

    在项目启动时,会在数据库新建66张表(版本不同,表的数量可能不同)

    1.对表分类

    清单:

    通用数据表

    流程定义存储表

    身份数据表

    运行时流程数据表

    历史流程数据表

    2.流程启动到结束数据库变化

    ​ 部署完毕后,act_re_deployment表中会有一条部署记录,记录这次部署的基本信息,然后是act_ge_bytearray表中有两条记录,记录的是本次上传的bpmn文件和对应的图片文件,每条记录都有act_re_deployment表的外键关联,然后是act_re_procdef表中有一条记录,记录的是该bpmn文件包含的基本信息,包含act_re_deployment表外键。

    流程启动,首先向act_ru_execution表中插入一条记录,记录的是这个流程定义的执行实例,其中id和proc_inst_id相同都是流程执行实例id,也就是本次执行这个流程定义的id,包含流程定义的id外键。

    然后向act_ru_task插入一条记录,记录的是第一个任务的信息,也就是开始执行第一个任务。包括act_ru_execution表中的execution_id外键和proc_inst_id外键,也就是本次执行实例id。

    然后向act_hi_procinst表和act_hi_taskinst表中各插入一条记录,记录的是本次执行实例和任务的历史记录:

    任务提交后,首先向act_ru_variable表中插入变量信息,包含本次流程执行实例的两个id外键,但不包括任务的id,因为setVariable方法设置的是全局变量,也就是整个流程都会有效的变量:

    当流程中的一个节点任务完成后,进入下一个节点任务,act_ru_task表中这个节点任务的记录被删除,插入新的节点任务的记录。

    同时act_ru_execution表中的记录并没有删除,而是将正在执行的任务变成新的节点任务。

    同时向act_hi_var_inst和act_hi_taskinst插入历史记录。

    整个流程执行完毕,act_ru_task,act_ru_execution和act_ru_variable表相关记录全被清空。

    全程有一个表一直在记录所有动作,就是act_hi_actinst表:

    以上就是flowable流程启动到结束的所有流程的变化。

    四.flowable中的五个引擎

    • 内容引擎 ContentEngine
    • 身份识别引擎 IdmEngine
    • 表单引擎 FormEngine
    • 决策引擎DmnEngine
    • 流程引擎 ProcessEngine

    1.流程引擎 ProcessEngine
    1.1 **RepositoryService

    管理流程定义

    1.2 **RuntimeService

    执行管理,包括启动、推进、删除流程实例等操作

    1.3 **TaskService

    任务管理

    1.4 **HistoryService

    历史管理(执行完的数据的管理)

    1.5 IdentityService

    组织机构管理

    1.6 FormService

    一个可选服务,任务表单管理

    1.7 ManagerService

    获取引擎所在的数据库中存在的表、获取表的元数据信息、创建删除等作业、执行命令类、执行自定义SQL、操作事件日志。

    1.8 DynamicBpmnService

    动态修改Bpmn流程定义以及部署库等操作。

    2.内容引擎ContentEngine

    2.1 内容引擎包含的服务有:ContentService和ContentManagementService。

    2.2 ContentManagementService提供对数据库表的管理操作。

    Map<String, Long> getTableCount(); 获取每个表的记录数量;
    String getTableName(Class<?> flowableEntityClass);根据实体类获得对应的数据库表名
    TableMetaData getTableMetaData(String tableName);根据实体类获得对应的数据库表名
    TablePageQuery createTablePageQuery();创建一个可以进行排序、根据条件分页的查询类
    3.身份识别引擎 IdmEngine

    身份识别引擎包含的服务有:IdmIdentityService、IdmManagementService、IdmEngineConfiguration。

    3.1 IdmIdentityService

    • 提供用户的创建、修改、删除、密码修改、登录、用户头像设置等;
    • 提供组Group的创建、删除、用户与组关系的关联、删除关联;
    • 提供权限的创建、删除、关联等.

    3.2 IdmManagementService

    对身份识别相关的数据库表进行统计、获取表的列信息。

    3.3 IdmEngineConfiguration

    提供数据库配置信息。

    4.表单引擎 FormEngine

    4.1 FormManagementService

    提供对数据库表的管理操作。

    4.2 FormRepositoryService

    表单资源服务。

    4.3 FormService

    提供表单实例的增删改查操作服务。

    5.决策引擎DmnEngine

    5.1 DmnManagementService

    该类主要用于获取一系列的数据表元数据信息。

    5.2 DmnRepositoryService

    动态部署流程资源。

    5.3 DmnRuleService

    按照规则启动流程实例。

    5.4 DmnHistoryService

    提供对决策执行历史的访问的服务。

    标签: