Flowable工作流-基础

Flowable基础

B站学习地址点击跳转

中文官方文档地址https://tkjohn.github.io/flowable-userguide/

新建项目普通maven项目略

引入配置文件

<dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.12</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.flowable</groupId>
      <artifactId>flowable-engine</artifactId>
      <version>6.3.0</version>
    </dependency>
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>5.1.48</version>
    </dependency>

以上引入 junit测试、flowable工作流以及mysql驱动

初始化数据库及获取ProcessEngine

@Test
    public void testProcessEngine() {
        ProcessEngineConfiguration configuration =
                ProcessEngineConfiguration.createStandaloneProcessEngineConfiguration();
        configuration.setJdbcDriver("com.mysql.cj.jdbc.Driver");
        // 下面链接报错:Error initialising eventregistry data model
//        configuration.setJdbcUrl("jdbc:mysql://localhost:3306/flowable?serverTimezone=UTC");
        configuration.setJdbcUrl("jdbc:mysql://localhost:3306/flowable?serverTimezone=UTC&nullCatalogMeansCurrent=true&useSSL=false&characterEncoding=utf8");
        configuration.setJdbcUsername("root");
        configuration.setJdbcPassword("123456");
        // 如果数据库中的表结构不存在,则新建
        configuration.setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE);
        ProcessEngine processEngine = configuration.buildProcessEngine();
        System.out.println(processEngine);
    }

 

注:如果jdbcUrl不加 '&nullCatalogMeansCurrent=true 会报错Error initialising eventregistry data model

运行方法,数据库会生成47个表,引入的同样包B站up主生成了30个,我这边生成了47个

 

集成日志

    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-api</artifactId>
      <version>1.7.21</version>
    </dependency>
    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-log4j12</artifactId>
      <version>1.7.21</version>
    </dependency>

 新增日志配置文件'log4j.properties'

log4j.rootLogger=DEBUG, CA

log4j.appender.CA=org.apache.log4j.ConsoleAppender
log4j.appender.CA.layout=org.apache.log4j.PatternLayout
log4j.appender.CA.layout.ConversionPattern=%d{HH:mm:ss,SSS} %-5p [%c{1}] %m%n

运行项目就正常打印日志了

部署流程

使用官方文档的流程文件

 流程介绍可以查看官网,https://tkjohn.github.io/flowable-userguide/#_deploying_a_process_definition

<?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>
holiday-request.bpmn20.xml

将上面的XML保存在src/main/resources文件夹下名为holiday-request.bpmn20.xml的文件中。

更改测试类,添加before,运行前初始化ProcessEngineConfiguration 

    ProcessEngineConfiguration configuration = null;
    @Before
    public void before() {
        configuration =
                ProcessEngineConfiguration.createStandaloneProcessEngineConfiguration();
        configuration.setJdbcDriver("com.mysql.jdbc.Driver");
        configuration.setJdbcUrl("jdbc:mysql://localhost:3306/flowable?serverTimezone=UTC&nullCatalogMeansCurrent=true&useSSL=false&characterEncoding=utf8");
        configuration.setJdbcUsername("root");
        configuration.setJdbcPassword("123456");
    }

部署流程

@Test
    public void testDeploy() {
        // 获取流程定义对象 ProcessEngine
        ProcessEngine processEngine = configuration.buildProcessEngine();
        // 完成流程的部署操作 = act_re_deployment   act_ge_bytearray  act_re_procdef
        Deployment deploy = processEngine.getRepositoryService()
                .createDeployment()
                .addClasspathResource("holiday-request.bpmn20.xml")
                .name("请假流程")
                .deploy();
        System.out.println("流程部署id:" + deploy.getId());
        System.out.println("流程部署名称:" + deploy.getName());
    }

查询流程

@Test
    public void queryDeploy() {
        ProcessEngine processEngine = configuration.buildProcessEngine();
        // 查询流程定义信息
        processEngine.getRepositoryService()
                .createProcessDefinitionQuery()
                .list()
                .forEach(processDefinition -> {
                    System.out.println("流程定义id:" + processDefinition.getId());
                    System.out.println("流程定义名称:" + processDefinition.getName());
                    System.out.println("流程定义key:" + processDefinition.getKey());
                    System.out.println("流程定义版本:" + processDefinition.getVersion());
                });
        // 根据部署id查询单个流程信息
        ProcessDefinition processDefinition = processEngine.getRepositoryService()
                .createProcessDefinitionQuery()
                .deploymentId("1")
                .singleResult();
        System.out.println("流程定义id:" + processDefinition.getId());
        System.out.println("流程定义名称:" + processDefinition.getName());
        System.out.println("流程定义key:" + processDefinition.getKey());
        System.out.println("流程定义版本:" + processDefinition.getVersion());
    }

删除部署流程

    @Test
    public void deleteDeploy() {
        ProcessEngine processEngine = configuration.buildProcessEngine();
        processEngine.getRepositoryService()
                // Boolean 是否级联删除部署id 对应的所有信息,包括流程定义、流程实例、任务、变量、附件等
                .deleteDeployment("1", true);
    }

新增流程触发引擎类

官方的bpm文件中流程流转有两个类需要新建

 直接在项目中新建类

package org.flowable;

import org.flowable.engine.delegate.DelegateExecution;
import org.flowable.engine.delegate.JavaDelegate;

public class SendRejectionMail implements JavaDelegate {
    /*
        这是一个flowable中的触发器,当流程被驳回时,会触发这个方法
     */
    @Override
    public void execute(DelegateExecution delegateExecution) {
        System.out.println("拒绝请假申请");
    }
}

 

package org.flowable;

import org.flowable.engine.delegate.DelegateExecution;
import org.flowable.engine.delegate.JavaDelegate;

public class CallExternalSystemDelegate  implements JavaDelegate {
    /*
        这是一个flowable中的触发器,当流程被驳回时,会触发这个方法
     */
    @Override
    public void execute(DelegateExecution delegateExecution) {
        System.out.println("通过申请");
    }
}

 

启动流程实例

如果是自动任务的话,启动流程会完整执行完才会返回。

    //启动流程实例
    @Test
    public void startProcessInstance() {
        ProcessEngine processEngine = configuration.buildProcessEngine();
        //构建流程变量
        Map<String, Object> variableMap = new HashMap<>();
//模拟请假流程的参数 variableMap.put(
"employee","张三"); variableMap.put("day",3); variableMap.put("reason","回家玩玩"); ProcessInstance holidayRequest = processEngine.getRuntimeService() .startProcessInstanceByKey("holidayRequest", variableMap); System.out.println("holidayRequest.getProcessDefinitionId() = " + holidayRequest.getProcessDefinitionId()); System.out.println("holidayRequest.getId() = " + holidayRequest.getId()); System.out.println("holidayRequest.getProcessInstanceId() = " + holidayRequest.getProcessInstanceId()); System.out.println("holidayRequest.getActivityId() = " + holidayRequest.getActivityId()); }

查询流转到lisi的任务

@Test
    public void queryTask() {
        ProcessEngine processEngine = configuration.buildProcessEngine();
        TaskService taskService = processEngine.getTaskService();
        List<Task> taskList = taskService.createTaskQuery()
                //指定流程编号
                .processDefinitionKey("holidayRequest")
                .taskAssignee("lisi")
                .list();
        taskList.forEach(task -> {
            System.out.println("task.getId() = " + task.getId());
            System.out.println("task.getName() = " + task.getName());
            System.out.println("task.getProcessInstanceId() = " + task.getProcessInstanceId());
            System.out.println("task.getAssignee() = " + task.getAssignee());
        });
    }

 执行/完成任务

@Test
    public void testCompleteTask() {
        ProcessEngine processEngine = configuration.buildProcessEngine();
        TaskService taskService = processEngine.getTaskService();

        List<Task> taskList = taskService.createTaskQuery()
                //指定流程编号
                .processDefinitionKey("holidayRequest")
                .taskAssignee("lisi")
                .list();
        Task task = taskList.get(0);
        // 构建流程变量
        Map<String, Object> variableMap = new HashMap<>();
        variableMap.put("approved",false);
        // 完成任务
        taskService.complete(task.getId(),variableMap);
    }

 流程查询

暂空

FlowableUi画流程图

可以到中文手册网站下载官网jar包

https://tkjohn.github.io/flowable-userguide/#flowableUIApps

我这里下载的是6.6.0版本,快捷下载链接=>

下载完成后解压打开war里面内容

 找到flowable-ui.war,然后进入命令行启动即可(如果需要换数据库可以进入文件中修改)

java -jar flowable-ui.war

 

 启动完成后访问地址:

http://localhost:8080/flowable-ui

输入账号密码  admin/test  登陆之后点击第二个橙色图标

 进入之后点击右上角的创建流程,名称 模型key 自己根据定义,后面可以修改的

进入后就可以画图了,默认有个空的圆圈,代表空的启动事件,现在准备画个图工作流如下(审批可以通过或者拒绝):

请假 -> 审批 -> 结束  

默认空圆圈代表已经发起请假流程,下一个需要添加 经理审批 ,鼠标移入圆圈点击右侧的人头分配给特定人的任务

 右侧就生成了个长方形方格,双击添加流程名称,或者下面菜单修改名称,然后再添加 分配用户 (那些人可以审核)我这里分配给wangwu

 我这里没有身份存储就分给固定人wangwu

 

分配后点击确定就显示分配人

 经理审批有多个状态,同意或者拒绝。所以下一个是个网关,

1、只有一个选择的排斥网关,可以从左侧的菜单拖动进去,

2、也可以点击经理审批,然后点击右侧的X 图标

 

然后从左侧找到活动,拖入两个服务任务,一个是同意审批后续流程,一个是拒绝审批后续流程,网关的指向箭头需要有条件,点击线条可以编辑这条流的执行条件

同意审批的线条输入${approved} ,等同于 ${approved==true},代表传入的参数approved==true则执行这条流程

拒绝请假的线条输入${approved==false},传入的参数approved==false则执行这条流程

服务任务需要自己添加类,点击服务任务,然后找到下面菜单 类 选项输入我们处理同意审批后的类完整路径,

 新建同意审批和拒绝审批类

package org.flowable;

import org.flowable.engine.delegate.DelegateExecution;
import org.flowable.engine.delegate.JavaDelegate;

public class AgreeLeaveDelegate implements JavaDelegate {
    @Override
    public void execute(DelegateExecution delegateExecution) {
        System.out.println("同意       请假流程,执行后续逻辑......");
    }
}
package org.flowable;

import org.flowable.engine.delegate.DelegateExecution;
import org.flowable.engine.delegate.JavaDelegate;

public class RefuseLeaveDelegate implements JavaDelegate {
    @Override
    public void execute(DelegateExecution delegateExecution) {
        System.out.println("拒绝         请假流程,执行后续逻辑......");
    }
}

然后分别配置到对于的流程下面,需要是完整路径,添加结束流程图标,并把两条分支指向结束

 然后保存关闭,点击打开后右上角有个下载的图标,下载后是个xml,复制到服务器resource下面

注:最好不要使用中文或者特殊符号

 

 执行流程

部署流程

新增测试类Test02,然后拷贝上面的ProcessEngineConfiguration配置@Before

ProcessEngineConfiguration configuration = null;
    @Before
    public void before() {
        configuration =
                ProcessEngineConfiguration.createStandaloneProcessEngineConfiguration();
        configuration.setJdbcDriver("com.mysql.jdbc.Driver");
        configuration.setJdbcUrl("jdbc:mysql://localhost:3306/flowable?serverTimezone=UTC&nullCatalogMeansCurrent=true&useSSL=false&characterEncoding=utf8");
        configuration.setJdbcUsername("root");
        configuration.setJdbcPassword("123456");
    }
    @Test
    public void testDeploy() {
        ProcessEngine processEngine = configuration.buildProcessEngine();
        Deployment deploy = processEngine.getRepositoryService()
                .createDeployment()
                .addClasspathResource("xxx公司请假流程.bpmn20.xml")
                .name("xxx公司请假流程")
                .deploy();
        System.out.println("流程部署id:" + deploy.getId());
        System.out.println("流程部署名称:" + deploy.getName());
    }

点击右键开始部署该流程,执行后打印信息

流程部署id:27501
流程部署名称:xxx公司请假流程

我们可以到下面三个表查看,代表部署成功,也可以执行程序查询

act_re_deployment   act_ge_bytearray  act_re_procdef

 

 启动实例

@Test
    public void startProcessInstance() {
        ProcessEngine processEngine = configuration.buildProcessEngine();
        Map<String, Object> variableMap = new HashMap<>();
        variableMap.put("employee","张三");
        variableMap.put("day",3);
        variableMap.put("reason","我想回家玩玩");
        ProcessInstance holidayRequest = processEngine.getRuntimeService()
                .startProcessInstanceByKey("xxx-qjlc-v01", variableMap);
        System.out.println("启动实例的实例id:" + holidayRequest.getId());
        System.out.println("启动实例的流程定义id:" + holidayRequest.getProcessDefinitionId());
        System.out.println("启动实例的流程定义key:" + holidayRequest.getProcessDefinitionKey());
    }

启动实例使用的ProcessDefinitionKey,就是创建流程的时候的模型key,也是xml中的id,启动后打印如下:

启动实例的实例id:30001
启动实例的流程定义id:xxx-qjlc-v01:1:27504
启动实例的流程定义key:xxx-qjlc-v01

根据流程图,提交后的就需要wangwu审批,所以我们可以查询wangwu是否有待办任务

查询待办任务

@Test
    public void queryTask() {
        ProcessEngine processEngine = configuration.buildProcessEngine();
        processEngine.getTaskService()
                .createTaskQuery()
                //这里输入指定人
                .taskAssignee("wangwu")
                .list()
                .forEach(task -> {
                    System.out.println("任务id:" + task.getId());
                    System.out.println("任务名称:" + task.getName());
                    System.out.println("任务创建时间:" + DateFormatUtils.format(task.getCreateTime(),"yyyy-MM-dd HH:mm:ss"));
                    System.out.println("任务所属流程实例id:" + task.getProcessInstanceId());
                });
    }

打印如下,可以看到有个待办任务,名字是经理审批

任务id:30008
任务名称:经理审批
任务创建时间:2024-04-18 00:27:27
任务所属流程实例id:30001

完成任务

上面的可以看到任务id是30008,完成任务需要使用任务id,先模拟个拒绝审批

@Test
    public void testCompleteTask() {
        ProcessEngine processEngine = configuration.buildProcessEngine();
        TaskService taskService = processEngine.getTaskService();
        // 构建流程变量
        Map<String, Object> variableMap = new HashMap<>();
        variableMap.put("approved",false);
        variableMap.put("remarks","想出去玩玩?拒绝");
        // 完成任务
        taskService.complete("30008",variableMap);
    }

运行后,在日志里面搜索可以看到打印了拒绝的服务任务,自动执行了RefuseLeaveDelegate。

 重新执行同意流程

@Test
    public void test02(){
        ProcessEngine processEngine = configuration.buildProcessEngine();
        Map<String, Object> variableMap = new HashMap<>();
        variableMap.put("employee","张三");
        variableMap.put("day",360);
        variableMap.put("reason","不给玩就辞工");
        ProcessInstance holidayRequest = processEngine.getRuntimeService()
                .startProcessInstanceByKey("xxx-qjlc-v01", variableMap);
        System.out.println("test02  启动实例的实例id:" + holidayRequest.getId());
        System.out.println("test02  启动实例的流程定义id:" + holidayRequest.getProcessDefinitionId());
        System.out.println("test02  启动实例的流程定义key:" + holidayRequest.getProcessDefinitionKey());

        //因为只有一个任务,所以可以单个查询,如果多个待办任务,使用singleResult会报错
        Task task = processEngine.getTaskService()
                .createTaskQuery()
                //这里输入指定人
                .taskAssignee("wangwu")
                .singleResult();
        System.out.println("test02  待办任务,任务id:"+task.getId());

        TaskService taskService = processEngine.getTaskService();
        // 构建流程变量
        Map<String, Object> variableMap2 = new HashMap<>();
        variableMap2.put("approved",true);
        variableMap2.put("remarks","好吧好吧,出去玩吧");
        // 完成任务
        taskService.complete(task.getId(),variableMap2);
        System.out.println("test02  任务完成");

    }

运行后可以看到因为approved给了true同意申请,日志打印了同意申请的Delegate服务任务

 上面两个xxx公司请假流程执行完之后记录就会移动到act_hi 开头的表里面,这部分表都是历史表,我们可以通过查询历史表获取工作流的执行信息。

历史查询

createHistoricProcessInstanceQuery:流程实例的历史信息

用于查询已完成的流程实例的历史数据,可以获取已结束的流程实例的详细信息,比如流程实例的ID、开始时间、结束时间等。对于表:act_hi_procinst

@Test
    public void queryHistoryProcessInstance() {
        ProcessEngine processEngine = configuration.buildProcessEngine();
        // 用于查询流程实例的历史信息
        processEngine.getHistoryService().createHistoricProcessInstanceQuery()
                .processDefinitionKey("xxx-qjlc-v01")
                .list()
                .forEach(x ->{
                    //使用中文打印参数信息
                    System.out.println("流程实例id:" + x.getId());
                    System.out.println("流程实例开始时间:" + DateFormatUtils.format(x.getStartTime(),"yyyy-MM-dd HH:mm:ss"));
                    System.out.println("流程实例结束时间:" + DateFormatUtils.format(x.getEndTime(),"yyyy-MM-dd HH:mm:ss"));
                    System.out.println("流程实例所属流程定义id:" + x.getProcessDefinitionId());
                });
    }
DateFormatUtils 只是为了把时间格式化,可以使用自己的时间格式化类,我这边使用的是 org.apache.commons.lang3.time

 打印结果如下,流程实例id,一个是30001一个是35001.

流程实例id:30001
流程实例开始时间:2024-04-18 00:27:26
流程实例结束时间:2024-04-18 00:38:30
流程实例所属流程定义id:xxx-qjlc-v01:1:27504
流程实例id:35001
流程实例开始时间:2024-04-18 00:43:55
流程实例结束时间:2024-04-18 00:44:56
流程实例所属流程定义id:xxx-qjlc-v01:1:27504

 createHistoricActivityInstanceQuery:活动实例的历史信息

上面的是整个流程实例的信息,流程实例的每个节点信息,对应的表:act_hi_actinst

@Test
    public void queryHistoryProcessInstance2() {
        ProcessEngine processEngine = configuration.buildProcessEngine();
        List<HistoricActivityInstance> resultList = processEngine.getHistoryService().createHistoricActivityInstanceQuery()
                .processDefinitionId("xxx-qjlc-v01:1:27504")
//                .processInstanceId("35001")
                .list();
        System.out.println(
                "|      " + "活动id" + "|       " +
                        "流程开始时间" + "|       " +
                        "流程结束时间" + "|       " +
                        "流程实例id" + "|       " +
                        "ActivityName" + "|"
        );
        resultList.forEach(x ->{
                    System.out.println(
                            "|      " + x.getId() + "|      " +
                                    DateFormatUtils.format(x.getStartTime(),"yyyy-MM-dd HH:mm:ss") + "|     " +
                                    DateFormatUtils.format(x.getEndTime(),"yyyy-MM-dd HH:mm:ss") + "|       " +
                                    x.getProcessInstanceId() + "|        "+
                                    x.getActivityName() + "|"
                    );
                });
    }

打印结果如下,根据实例id和流程图可以看出来,

第一条是空开始事件,第二条是经理审批,第三天是网关,第四条是自动服务任务,第五条是结束事件

查询出来流程的流转信息

createHistoricTaskInstanceQuery

包含该流程实例下跟人相关的活动,不包括未分配任务执行人的网关、开始事件和结束事件,主要查询的是任务实例

 

@Test
    public void queryHistoryTask() {
        ProcessEngine processEngine = configuration.buildProcessEngine();
        List<HistoricTaskInstance> resultList = processEngine.getHistoryService().createHistoricTaskInstanceQuery()
                .processDefinitionKey("xxx-qjlc-v01")
//                .processDefinitionId("xxx-qjlc-v01:1:27504")
                .list();
        System.out.println(
                "|      " + "任务id" + "|       " +
                        "任务名称" + "|       " +
                        "任务创建时间" + "|       " +
                        "任务结束时间" + "|       " +
                        "任务处理人" + "|"
        );
        resultList.forEach(x ->{
            System.out.println(
                    "|      " + x.getId() + "|       " +
                            x.getName() + "|       " +
                            DateFormatUtils.format(x.getCreateTime(),"yyyy-MM-dd HH:mm:ss") + "|       " +
                            DateFormatUtils.format(x.getEndTime(),"yyyy-MM-dd HH:mm:ss") + "|       " +
                            x.getAssignee() + "|");
        });
    }

查询出来的是两个跟人相关的活动信息

 createHistoricVariableInstanceQuery:查询已完成的变量实例的历史数据

用于查询已完成的变量实例的历史数据,可以获取流程中已经被设置或修改过的变量的详细信息,比如变量的名称、类型、值、所属流程实例等。

@Test
    public void queryHistoryVariable() {
        ProcessEngine processEngine = configuration.buildProcessEngine();
        List<HistoricVariableInstance> resultList = processEngine.getHistoryService().createHistoricVariableInstanceQuery()
                .processInstanceId("30001")
                .list();
        System.out.println(
                "|      " + "参数id" + "|       " +
                        "实例id" + "|       " +
                        "变量名称" + "|       " +
                        "变量值" + "|"
        );
        resultList.forEach(x ->{
            System.out.println(
                    "|      " + x.getId() + "|       " +
                            x.getProcessInstanceId() + "|       " +
                            x.getVariableName() + "|       " +
                            x.getValue() + "|");
        });
    }

打印如下:

 完整代码

package org.example.t01;

import org.apache.commons.lang3.time.DateFormatUtils;
import org.flowable.engine.ProcessEngine;
import org.flowable.engine.ProcessEngineConfiguration;
import org.flowable.engine.TaskService;
import org.flowable.engine.history.HistoricActivityInstance;
import org.flowable.engine.repository.Deployment;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.task.api.Task;
import org.flowable.task.api.history.HistoricTaskInstance;
import org.flowable.variable.api.history.HistoricVariableInstance;
import org.junit.Before;
import org.junit.Test;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class Test02 {

    ProcessEngineConfiguration configuration = null;
    @Before
    public void before() {
        configuration =
                ProcessEngineConfiguration.createStandaloneProcessEngineConfiguration();
        configuration.setJdbcDriver("com.mysql.jdbc.Driver");
        configuration.setJdbcUrl("jdbc:mysql://localhost:3306/flowable?serverTimezone=UTC&nullCatalogMeansCurrent=true&useSSL=false&characterEncoding=utf8");
        configuration.setJdbcUsername("root");
        configuration.setJdbcPassword("123456");
    }
    @Test
    public void testDeploy() {
        // 获取流程定义对象 ProcessEngine
        ProcessEngine processEngine = configuration.buildProcessEngine();
        // 完成流程的部署操作 = act_re_deployment   act_ge_bytearray  act_re_procdef
        Deployment deploy = processEngine.getRepositoryService()
                .createDeployment()
                .addClasspathResource("xxx公司请假流程.bpmn20.xml")
                .name("xxx公司请假流程")
                .deploy();
        System.out.println("流程部署id:" + deploy.getId());
        System.out.println("流程部署名称:" + deploy.getName());
    }

    @Test
    public void startProcessInstance() {
        ProcessEngine processEngine = configuration.buildProcessEngine();
        Map<String, Object> variableMap = new HashMap<>();
        variableMap.put("employee","张三");
        variableMap.put("day",3);
        variableMap.put("reason","我想回家玩玩");
        ProcessInstance holidayRequest = processEngine.getRuntimeService()
                .startProcessInstanceByKey("xxx-qjlc-v01", variableMap);
        System.out.println("启动实例的实例id:" + holidayRequest.getId());
        System.out.println("启动实例的流程定义id:" + holidayRequest.getProcessDefinitionId());
        System.out.println("启动实例的流程定义key:" + holidayRequest.getProcessDefinitionKey());
    }
    @Test
    public void queryTask() {
        ProcessEngine processEngine = configuration.buildProcessEngine();
        processEngine.getTaskService()
                .createTaskQuery()
                //这里输入指定人
                .taskAssignee("wangwu")
                .list()
                .forEach(task -> {
                    System.out.println("任务id:" + task.getId());
                    System.out.println("任务名称:" + task.getName());
                    System.out.println("任务创建时间:" + DateFormatUtils.format(task.getCreateTime(),"yyyy-MM-dd HH:mm:ss"));
                    System.out.println("任务所属流程实例id:" + task.getProcessInstanceId());
                });
    }

    @Test
    public void testCompleteTask() {
        ProcessEngine processEngine = configuration.buildProcessEngine();
        TaskService taskService = processEngine.getTaskService();
        // 构建流程变量
        Map<String, Object> variableMap = new HashMap<>();
        variableMap.put("approved",false);
        variableMap.put("remarks","想出去玩玩?拒绝");
        // 完成任务
        taskService.complete("30008",variableMap);
    }


    @Test
    public void test02(){
        ProcessEngine processEngine = configuration.buildProcessEngine();
        Map<String, Object> variableMap = new HashMap<>();
        variableMap.put("employee","张三");
        variableMap.put("day",360);
        variableMap.put("reason","不给玩就辞工");
        ProcessInstance holidayRequest = processEngine.getRuntimeService()
                .startProcessInstanceByKey("xxx-qjlc-v01", variableMap);
        System.out.println("test02  启动实例的实例id:" + holidayRequest.getId());
        System.out.println("test02  启动实例的流程定义id:" + holidayRequest.getProcessDefinitionId());
        System.out.println("test02  启动实例的流程定义key:" + holidayRequest.getProcessDefinitionKey());

        //因为只有一个任务,所以可以单个查询,如果多个待办任务,使用singleResult会报错
        Task task = processEngine.getTaskService()
                .createTaskQuery()
                //这里输入指定人
                .taskAssignee("wangwu")
                .singleResult();
        System.out.println("test02  待办任务,任务id:"+task.getId());

        TaskService taskService = processEngine.getTaskService();
        // 构建流程变量
        Map<String, Object> variableMap2 = new HashMap<>();
        variableMap2.put("approved",true);
        variableMap2.put("remarks","好吧好吧,出去玩吧");
        // 完成任务
        taskService.complete(task.getId(),variableMap2);
        System.out.println("test02  任务完成");

    }
    @Test
    public void queryHistoryProcessInstance() {
        ProcessEngine processEngine = configuration.buildProcessEngine();
        List<HistoricActivityInstance> resultList = processEngine.getHistoryService().createHistoricActivityInstanceQuery()
                .processDefinitionId("xxx-qjlc-v01:1:27504")
//                .processInstanceId("35001")
                .list();
        System.out.println(
                "|      " + "活动id" + "|       " +
                        "流程开始时间" + "|       " +
                        "流程结束时间" + "|       " +
                        "流程实例id" + "|       " +
                        "ActivityName" + "|"
        );
        resultList.forEach(x ->{
                    System.out.println(
                            "|      " + x.getId() + "|      " +
                                    DateFormatUtils.format(x.getStartTime(),"yyyy-MM-dd HH:mm:ss") + "|     " +
                                    DateFormatUtils.format(x.getEndTime(),"yyyy-MM-dd HH:mm:ss") + "|       " +
                                    x.getProcessInstanceId() + "|        "+
                                    x.getActivityName() + "|"
                    );
                });
    }
    @Test
    public void queryHistoryTask() {
        ProcessEngine processEngine = configuration.buildProcessEngine();
        List<HistoricTaskInstance> resultList = processEngine.getHistoryService().createHistoricTaskInstanceQuery()
                .processDefinitionKey("xxx-qjlc-v01")
//                .processDefinitionId("xxx-qjlc-v01:1:27504")
                .list();
        System.out.println(
                "|      " + "任务id" + "|       " +
                        "任务名称" + "|       " +
                        "任务创建时间" + "|       " +
                        "任务结束时间" + "|       " +
                        "任务处理人" + "|"
        );
        resultList.forEach(x ->{
            System.out.println(
                    "|      " + x.getId() + "|       " +
                            x.getName() + "|       " +
                            DateFormatUtils.format(x.getCreateTime(),"yyyy-MM-dd HH:mm:ss") + "|       " +
                            DateFormatUtils.format(x.getEndTime(),"yyyy-MM-dd HH:mm:ss") + "|       " +
                            x.getAssignee() + "|");
        });
    }

    @Test
    public void queryHistoryVariable() {
        ProcessEngine processEngine = configuration.buildProcessEngine();
        List<HistoricVariableInstance> resultList = processEngine.getHistoryService().createHistoricVariableInstanceQuery()
                .processInstanceId("30001")
                .list();
        System.out.println(
                "|      " + "参数id" + "|       " +
                        "实例id" + "|       " +
                        "变量名称" + "|       " +
                        "变量值" + "|"
        );
        resultList.forEach(x ->{
            System.out.println(
                    "|      " + x.getId() + "|       " +
                            x.getProcessInstanceId() + "|       " +
                            x.getVariableName() + "|       " +
                            x.getValue() + "|");
        });
    }



}
Test02.java

扩展在JavaDelegate里面获取参数信息直接使用delegateExecution.getVariable就可以获取

public class RefuseLeaveDelegate implements JavaDelegate {
    @Override
    public void execute(DelegateExecution delegateExecution) {
        // 获取参数信息
        String remarks = (String) delegateExecution.getVariable("remarks");
        // 执行自定义逻辑
        System.out.println("拒绝了请假流程,并留言: " + remarks);

    }
}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

posted @ 2024-06-04 15:25  苦心明  阅读(152)  评论(0)    收藏  举报