flowable 工作流

1 快速入门案例

1.1 maven 依赖

    <dependencies>
        <dependency>
            <groupId>org.flowable</groupId>
            <artifactId>flowable-engine</artifactId>
            <version>6.6.0</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.20</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.30</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.7.30</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.2</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.7.22</version>
        </dependency>
    </dependencies>

1.2 基本操作

1.2.1 编码准备

这里一官网请假流程案例为例
在这里插入图片描述

  • 我们假设该过程是通过提供一些信息开始的,例如员工姓名、请求的假期数量和描述。当然,这可以建模为流程中单独的第一步。但是,通过将其作为流程的“输入数据”,流程实例仅在发出实际请求时才实际创建。在另一种情况下,用户可以在提交之前改变主意并取消,但流程实例现在就在那里。在某些情况下,这可能是有价值的信息(例如,请求启动但未完成的次数),具体取决于业务目标。
  • 左边的圆圈称为开始事件。它是流程实例的起点。
  • 第一个矩形是用户任务。这是人类用户必须执行的过程中的一个步骤。在这种情况下,经理需要批准或拒绝该请求。
  • 根据经理的决定,专用网关(带有十字的菱形)会将流程实例路由到批准或拒绝路径。
  • 如果获得批准,我们必须在某个外部系统中注册请求,然后再次为原始员工执行用户任务,通知他们该决定。当然,这可以用电子邮件代替。
  • 如果被拒绝,则会向员工发送一封电子邮件,通知他们这一点。

resources 目录下 新建一个 holiday-request.bpmn20.xml 文件

<?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: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"
  xmlns:flowable="http://flowable.org/bpmn"
  typeLanguage="http://www.w3.org/2001/XMLSchema"
  expressionLanguage="http://www.w3.org/1999/XPath"
  targetNamespace="http://www.flowable.org/processdef">

  <process id="holidayRequest" name="Holiday Request" isExecutable="true">
    <startEvent id="startEvent"/>
    <sequenceFlow sourceRef="startEvent" targetRef="approveTask"/>
    <userTask id="approveTask" name="Approve or reject request"/>
    <sequenceFlow sourceRef="approveTask" targetRef="decision"/>
    <exclusiveGateway id="decision"/>
    <sequenceFlow sourceRef="decision" targetRef="externalSystemCall">
      <conditionExpression xsi:type="tFormalExpression">
        <![CDATA[
          ${approved}
        ]]>
      </conditionExpression>
    </sequenceFlow>
    <sequenceFlow  sourceRef="decision" targetRef="sendRejectionMail">
      <conditionExpression xsi:type="tFormalExpression">
        <![CDATA[
          ${!approved}
        ]]>
      </conditionExpression>
    </sequenceFlow>
    <serviceTask id="externalSystemCall" name="Enter holidays in external system"
        flowable:class="org.flowable.CallExternalSystemDelegate"/>
    <sequenceFlow sourceRef="externalSystemCall" targetRef="holidayApprovedTask"/>
    <userTask id="holidayApprovedTask" name="Holiday approved"/>
    <sequenceFlow sourceRef="holidayApprovedTask" targetRef="approveEnd"/>
    <serviceTask id="sendRejectionMail" name="Send out rejection email"
        flowable:class="org.flowable.SendRejectionMail"/>
    <sequenceFlow sourceRef="sendRejectionMail" targetRef="rejectEnd"/>
    <endEvent id="approveEnd"/>
    <endEvent id="rejectEnd"/>
  </process>
</definitions>

1.2.2 初始化 DB

    @Before
    public void init() {
        ProcessEngineConfiguration configuration = new StandaloneInMemProcessEngineConfiguration();
        configuration.setJdbcDriver("com.mysql.cj.jdbc.Driver");
        configuration.setJdbcUsername("root");
        configuration.setJdbcPassword("hwl123456");
        configuration.setJdbcUrl("jdbc:mysql://127.0.0.1:3306/flowable?allowMultiQueries=true&useUnicode=true&useSSL=false&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&autoReconnect=true&nullCatalogMeansCurrent=true");
        configuration.setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE);
        engine = configuration.buildProcessEngine();
    }

运行脚本后会初始化相关表,后面一点点介绍
在这里插入图片描述

1.2.3 部署流程

    @Test
    public void testDeploy() {
        RepositoryService repositoryService = engine.getRepositoryService();
        // 部署流程,部署后会在 act_re_deployment 和 act_ge_bytearray 表中添加记录
        Deployment deployment = repositoryService.createDeployment()
                .addClasspathResource("holiday-request.bpmn20.xml")
                // 指定流程名称
                .name("请假流程")
                .deploy();
        System.out.println(JSONUtil.toJsonPrettyStr(deployment));
    }

查看 act_re_deployment 表
在这里插入图片描述
查看 act_ge_bytearray,记录 xml 文本字节数组,通过 deployment_id 关联,
在这里插入图片描述

1.2.4 查询流程

    @Test
    public void testQuery() {
        RepositoryService repositoryService = engine.getRepositoryService();
        Deployment deployment = repositoryService.createDeploymentQuery()
                .deploymentId("1")
                .singleResult();
        System.out.println(deployment.getName());
    }

查看相关的 api 有列表查询、分页查询等

1.2.3 删除流程

    @Test
    public void testDelete() {
        // 如果部署的流程已启动则不能删除
        engine.getRepositoryService().deleteDeployment("1");
        // 如果流程已启动则相关的任务一并删除
        engine.getRepositoryService().deleteDeployment("1", true);
    }

1.2.4 发起流程

修改 holiday-request.bpmn20 文件,添加一个审批人
在这里插入图片描述

    @Test
    public void testStart() {
        RuntimeService runtimeService = engine.getRuntimeService();
        Map<String, Object> param = new HashMap<>(8);
        param.put("employee", "张三");
        param.put("days", 3);
        param.put("description", "请假回家");
        // 启动流程实例
        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("holidayRequest", param);
        // 启动后 act_ru_variable 表中记录参数信息
        System.out.println(processInstance.getName());
    }

发起流程后流程实例表 act_hi_procinst
在这里插入图片描述
流程任务表 act_ru_task,通过 proc_inst_id 和流程实例关联
在这里插入图片描述
流程执行过程 act_ru_execution,通过 proc_inst_id 和流程实例关联
在这里插入图片描述
提交参数表 act_ru_variable,通过 proc_inst_id 和流程实例关联,通过 execution_id 和执行过程关联
在这里插入图片描述

1.2.5 查询流程任务

    @Test
    public void testQueryTask() {
        TaskService taskService = engine.getTaskService();
        List<Task> list = taskService.createTaskQuery()
                // 指定流程类型
                .processDefinitionKey("holidayRequest")
                // 指定办理人,通常用于查询我的待办
                .taskAssignee("zhangsan")
                .list();
        System.out.println(JSONUtil.toJsonPrettyStr(list));
    }

1.2.6 执行任务

根据 xml 文件配置拒绝流程发送邮件类
在这里插入图片描述

    @Test
    public void testHandleTask() {
        TaskService taskService = engine.getTaskService();
        Map<String, Object> param = new HashMap<>();
        param.put("approved", false);
        // 完成任务
        taskService.complete("2509", param);
    }

执行后看到控制台输出拒绝邮件
查看流程实例表 act_hi_procinst
在这里插入图片描述
有流程持续时间、开始节点、结束节点
查看流程任务表 act_ru_task 、流程执行过程 act_ru_execution 和提交参数表 act_ru_variable 已经被清空

1.2.7 查看历史信息

流程审批后,相关的中间数据都已经被清理了。如果查看流程提交记录需要查看历史信息

    @Test
    public void testGetHistory() {
        HistoryService historyService = engine.getHistoryService();
        List<HistoricActivityInstance> list = historyService.createHistoricActivityInstanceQuery().processDefinitionId("holidayRequest:1:3")
                // 已结束的流程
                .finished()
                // 根据结束时间倒序排序
                .orderByHistoricActivityInstanceEndTime().desc()
                .list();
        for (HistoricActivityInstance instance: list) {
            System.out.println(JSONUtil.toJsonStr(instance));
        }
    }

历史执行记录表 act_hi_actinst
在这里插入图片描述
历史表单参数表 act_hi_varinst
在这里插入图片描述

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值