• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

Flowable工作流引擎

武飞扬头像
JJJJJJJJJAVA
帮助1

Flowable工作流引擎

Flowable-基础篇(根据BV1Pb4y1p7Ku整理)

一、简介

Flowable是BPMN的一个基于java的软件实现,不过Flowable不仅仅包括BPMN,还有DMN决策表和CMMN Case管理引擎,并且有自己的用户管理、微服务API等一系列功能,是一个服务平台。
学新通

官方手册:https://tkjohn.github.io/flowable-userguide/# introduction

二、数据库解析(数据库为代码创建,先看第三点:实例前的示例(官方文档的例子))

学新通
1、act_evt_log:日志表
学新通
2、act_ge_bytearray:二进制资源表
学新通
3、act_ge_bytearray:引擎属性表
学新通
4、act_hi_actinst:历史活动信息表
学新通
5、act_hi_attachment:流程历史附件表
学新通
6、act_hi_comment:历史审批意见表
学新通
7、act_hi_detail:历史详情表
学新通
8、act_hi_identitylink:历史参与的人员表
学新通
9、act_hi_procinst:历史流程记录表
学新通
10、act_hi_taskinst:历史任务表
学新通
11、act_hi_varinst:历史流程变量表
学新通
12、act_id_bytearray:用户组部署内容表
用户组的部署内容
13、act_id_group:所有用户组信息表
所有用户组的信息
14、act_id_info:所有用户信息表
所有用户的信息,账号密码
15、act_id_membership:用户和用户组关系表
用户和用户组的关系
16、act_id_priv:权限表
17、act_id_priv_mapping:用户权限关系表
18、act_id_property:用户变量表
用户的变量,存了版本号
19、act_id_token:用户访问记录表
20、ct_id_user:用户基本信息表
用户基本信息,包括邮箱等
21、act_procdef_info:流程定义信息表
学新通
22、act_re_deployment:流程部署表
学新通
23、act_re_model:流程模型表
学新通
24、act_re_procdef:流程定义表
学新通
25、act_ru_deadletter_job:运行时死信作业表
学新通
26、act_ru_event_subscr:运行时事件订阅表
学新通
27、act_ru_execution:运行时流程执行实例表
学新通
28、atc_ru_history_job:运行时历史信息表
29、act_ru_identitylink:运行时身份连接表
学新通
30、act_ru_job:运行时作业表
学新通
31、act_ru_suspended_job:运行时挂起的定时作业表
学新通
32、act_ru_task:运行时任务表
学新通
33、act_ru_timer_job:运行时定时作业表
学新通
34、act_ru_variable:运行时流程变量表
学新通

三、实例前的示例(官方文档的例子)

1、创建项目

创建一个maven项目
学新通
学新通
填写pom依赖
学新通

2、配置依赖
<properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

    <dependencies>
        <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>8.0.21</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.2</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
学新通
3、Test01

先创建数据库
学新通
创建Test01
学新通

public class Test01 {

    /*获取流程引擎对象*/
    @Test
    public void testProcessEngine(){
        // 获取ProcessEngineConfiguration对象
        ProcessEngineConfiguration configuration = new StandaloneInMemProcessEngineConfiguration();

        // 配置相关数据库连接信息(做演示就不封装了)
        configuration.setJdbcDriver("com.mysql.cj.jdbc.Driver");
        configuration.setJdbcUsername("root");
        configuration.setJdbcPassword("root");
        configuration.setJdbcUrl("jdbc:mysql://localhost:3306/flowable_learn?serverTimezone=UTC");

        // 如果数据库中的表结构不存在就新建
        configuration.setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE);
        // 通过ProcessEngineConfiguration构建我们需要的processEngine对象
        ProcessEngine processEngine = configuration.buildProcessEngine();
    }
}
学新通

运行程序
学新通
红色提示是由于没配置日志文件,运行完成后到数据库查看
学新通
可以看到已经创建了数据库表,这里使用的是5.7版本的数据库,值得注意的是,如果使用8.0版本的数据库,可能出现如下问题
学新通
添加日志配置
先添加pom依赖

<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} [%t] %-5p %c %x - %m%n

再次运行就可以看到已经有日志信息的输出
学新通

4、流程部署

流程部署定义
学新通
学新通
流程部署布置:配置文件:holiday-request.bpmn20.xml
将下面的XML保存在src/main/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>
学新通

我们来添加些备注以便看懂整个逻辑

<?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:流程主键,name:名称,可以修改,比如改为"请假流程"-->
    <process id="holidayRequest" name="Holiday Request" isExecutable="true">

        <startEvent id="startEvent"/>
        <!--targetRef:目标引用,走到下面的approveTask-->
        <sequenceFlow sourceRef="startEvent" targetRef="approveTask"/>

        <!--name="同意或者拒绝请假"-->
        <userTask id="approveTask" name="Approve or reject request"/>
        <!--targetRef目标引用为下面的排他网关decision-->
        <sequenceFlow sourceRef="approveTask" targetRef="decision"/>

        <!--排他网关(id:decision),有两个流程-->
        <exclusiveGateway id="decision"/>
        <!--流程1:targetRef="外部系统调用",就是走到管理员审批的流程中-->
        <sequenceFlow sourceRef="decision" targetRef="externalSystemCall">
            <!--条件表达式:${approved}如果为真就走这里-->
            <conditionExpression xsi:type="tFormalExpression">
                <![CDATA[
          ${approved}
        ]]>
            </conditionExpression>
        </sequenceFlow>
        <!--targetRef="发送拒绝邮件",就是直接走拒绝策略,就跳转到下面id="sendRejectionMail"-->
        <sequenceFlow  sourceRef="decision" targetRef="sendRejectionMail">
            <!--条件表达式:${!approved}:!表示取反,如果参数不为真就走这里-->
            <conditionExpression xsi:type="tFormalExpression">
                <![CDATA[
          ${!approved}
        ]]>
            </conditionExpression>
        </sequenceFlow>

        <!--name="在外部系统中输入假日"-->
        <serviceTask id="externalSystemCall" name="Enter holidays in external system"
                     flowable:class="org.flowable.CallExternalSystemDelegate"/>
        <sequenceFlow sourceRef="externalSystemCall" targetRef="holidayApprovedTask"/>

        <!--name="假期获批",targetRef="approveEnd"就是走到最下面结束-->
        <userTask id="holidayApprovedTask" name="Holiday approved"/>
        <sequenceFlow sourceRef="holidayApprovedTask" targetRef="approveEnd"/>

        <!--name="发送拒绝邮件",flowable:class就是用来处理发送邮件的操作,targetRef="rejectEnd"就是走到最下面结束-->
        <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>
学新通

我们再次对照下图来看,xml中从process id="holidayRequest"开始,就是对应下图的发起请假申请;然后走到approveTask,approveTask走到排他网关,排他网关有两个分支,根据$ {approved}和$ {!approved}来判断走哪个分支,就是对应下图的网关同意和拒绝两个分支:拒绝的话走到sendRejectionMail发送拒绝邮件,再跳转到rejectEnd结束;同意的话就是走到externalSystemCall,对应下图进入人事系统,然后走到holidayApprovedTask假期获批,最后跳转到approveEnd结束流程。
学新通
流程部署布置:代码实现
回到test01中
学新通

	ProcessEngineConfiguration configuration = null;

    @Before
    public void before(){
        /*配置数据库设置*/
        configuration = new StandaloneInMemProcessEngineConfiguration();
        configuration.setJdbcDriver("com.mysql.cj.jdbc.Driver");
        configuration.setJdbcUsername("root");
        configuration.setJdbcPassword("root");
        configuration.setJdbcUrl("jdbc:mysql://localhost:3306/flowable_learn?serverTimezone=UTC");
        // 如果数据库中的表结构不存在就新建
        configuration.setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE);
    }

    /**
     * 部署流程
     * */
    @Test
    public void testDeploy(){
        // 1.获取ProcessEngine对象
        ProcessEngine processEngine = configuration.buildProcessEngine();
        // 2.获取RepositoryService
        RepositoryService repositoryService = processEngine.getRepositoryService();
        // 3.完成流程的部署操作
        Deployment deploy = repositoryService.createDeployment()
                .addClasspathResource("holiday-request.bpmn20.xml")
                .name("请求流程")
                .deploy();

        System.out.println("deploy.getId():"   deploy.getId());
        System.out.println("deploy.getName():"   deploy.getName());
    }
学新通

运行测试程序
学新通
到数据库中查看
学新通
学新通
学新通
还需要注意ProcessEngine和四个Service之间的关系
学新通

流程部署布置:查询流程定义的信息
在test01中添加如下代码并运行
学新通

	 /**
     * 查询流程定义的信息
     * */
    @Test
    public void testDeployQuery(){
        // 获取ProcessEngine对象
        ProcessEngine processEngine = configuration.buildProcessEngine();
        // 获取RepositoryService资源管理服务
        RepositoryService repositoryService = processEngine.getRepositoryService();


        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
                // deploymentId要查找现有的id(可以去数据库中查看deployment中查看),否则会报空指针异常
                .deploymentId("2501")
                .singleResult();

        System.out.println("processDefinition.getDeploymentId():"   processDefinition.getDeploymentId());
        System.out.println("processDefinition.getName():"   processDefinition.getName());
        System.out.println("processDefinition.getDescription():"   processDefinition.getDescription());
        System.out.println("processDefinition.getId():"   processDefinition.getId());
    }
学新通

运行结果如下
学新通

若查询不存在的id
学新通

流程部署布置:删除流程定义
在test01中添加如下代码并运行
学新通

	/**
     * 删除流程定义
     * */
    @Test
    public void testDeleteDeploy(){
        // 获取ProcessEngine对象
        ProcessEngine processEngine = configuration.buildProcessEngine();
        // 获取RepositoryService资源管理服务
        RepositoryService repositoryService = processEngine.getRepositoryService();

        // 删除部署的流程(第一个参数是id,如果部署的流程启动了就不允许删除了;第二是参数是级联删除,若为true,则若流程启动了,相关的任务会一并被删除)
        repositoryService.deleteDeployment("1", false);
    }

运行后,查看日志信息可以得知数据库数据已被删除
学新通

四、启动流程实例(官方文档的例子)

在test01中继续添加代码
学新通

	/**
     * 启动流程实例
     * */
    @Test
    public void testRunProcess(){
        ProcessEngine processEngine = configuration.buildProcessEngine();

        // 我们需要通过RuntimeService来启动流程实例
        RuntimeService runtimeService = processEngine.getRuntimeService();
        //构建流程变量
        Map<String, Object> variables = new HashMap<>();
        variables.put("employee", "张三");
        variables.put("nrOfHolidays", "3");
        variables.put("description", "工作累了,出去玩玩");

        // 启动流程实例
        ProcessInstance holidayRequest = runtimeService.startProcessInstanceByKey("holidayRequest", variables);
        System.out.println("holidayRequest.getProcessDefinitionId():"   holidayRequest.getProcessDefinitionId());
        System.out.println("holidayRequest.getActivityId():"   holidayRequest.getActivityId()); // 当前活跃
        System.out.println("holidayRequest.getId():"   holidayRequest.getId());
    }
学新通

运行结果如下图所示(第二个参数:当前活跃的为0)
学新通
查询任务(查询自己需要审批的业务)
上面一步中员工发起了一个请假流程,接下里就会流转到经理这里来,我们现在指定这个经理为处理人
学新通
然后我们先删除掉之前的,即用“删除流程定义”方法把表act_ge_bytearray里面的数据都删除掉
删除完之后再执行一遍"部署流程"方法
学新通
学新通
然后运行"启动流程实例"方法
学新通
学新通
最后我们来添加一个查询任务方法,指定查询manager需要审批的任务
学新通

	/**
     * 查询任务
     * */
    @Test
    public void testQueryTask(){
        ProcessEngine processEngine = configuration.buildProcessEngine();
        TaskService taskService = processEngine.getTaskService();
        List<Task> list = taskService.createTaskQuery()
                .processDefinitionKey("holidayRequest") // 指定查询的流程编程
                .taskAssignee("manager") // 查询这个任务的处理人
                .list();

        for (Task task: list) {
            System.out.println("task.getProcessDefinitionId():"   task.getProcessDefinitionId());
            System.out.println("task.getName():"   task.getName());
            System.out.println("task.getAssignee():"   task.getAssignee());
            System.out.println("task.getDescription():"   task.getDescription());
            System.out.println("task.getId():"   task.getId());
        }
    }
学新通

学新通
执行任务(拒绝)
根据sendRejectionMail中的flowable:class创建类
学新通
学新通
写入拒绝流程
学新通

public class SendRejectionMail implements JavaDelegate {

    /**
     * 这是一个flowable的触发器
     * */
    @Override
    public void execute(DelegateExecution execution) {
        // 触发执行的逻辑,按照我们在流程中的定义应该给被拒绝的员工发送通知的邮件
        // 这里面可以通过邮件发送之类的,这里做模拟就只是写一个sout
        System.out.println("请假申请不通过,请安心工作");
    }
}

回到test01中书写"执行任务"方法
学新通

	/**
     * 执行任务
     * */
    @Test
    public void testCompleteTask(){
        ProcessEngine processEngine = configuration.buildProcessEngine();
        TaskService taskService = processEngine.getTaskService();
        Task task = taskService.createTaskQuery()
                .processDefinitionKey("holidayRequest")
                .taskAssignee("manager") //指定是经理
                .singleResult();

        // holiday-request.bpmn20.xml中${!approved}表示走拒绝策略,我们这里传一个${!approved}
        Map<String, Object> map = new HashMap<>();
        map.put("approved", false);

        // 完成任务
        taskService.complete(task.getId(), map);
    }
学新通

运行发现已经出现拒绝提示
学新通
回到数据库中查看,发现只剩历史记录有数据了,因为已经执行完一个流程了
学新通
学新通
历史任务查询
学新通

 	/**
     * 获取流程任务的历史数据
     * */
    @Test
    public void testHistory(){
        ProcessEngine processEngine = configuration.buildProcessEngine();
        HistoryService historyService = processEngine.getHistoryService();

        List<HistoricActivityInstance> list = historyService.createHistoricActivityInstanceQuery()
                .processDefinitionId("holidayRequest:1:17503") // 从act_hi_actinst中获取
                .finished() // 查询的历史记录的状态是已完成
                .orderByHistoricActivityInstanceEndTime().asc() //指定排序的字段和顺序
                .list();

        for (HistoricActivityInstance history: list) {
            System.out.println(history.getActivityName()   ":"   history.getAssignee()   "--"   history.getActivityId()   ":"   history.getDurationInMillis()   "毫秒");
        }
    }
学新通

学新通
运行代码,结果如下
学新通
到此一个完整流程结束
完整的Test01如下:

package com.ghost.flowable.test;

import org.flowable.engine.*;
import org.flowable.engine.history.HistoricActivityInstance;
import org.flowable.engine.impl.HistoricActivityInstanceQueryImpl;
import org.flowable.engine.impl.cfg.StandaloneInMemProcessEngineConfiguration;
import org.flowable.engine.repository.Deployment;
import org.flowable.engine.repository.ProcessDefinition;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.task.api.Task;
import org.junit.Before;
import org.junit.Test;

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

/**
 * flowable测试01
 *
 * @author ghost
 * @date 2022-09-06
 */
public class Test01 {

    /*获取流程引擎对象*/
    @Test
    public void testProcessEngine(){
        // 获取ProcessEngineConfiguration对象
        ProcessEngineConfiguration configuration = new StandaloneInMemProcessEngineConfiguration();

        // 配置相关数据库连接信息(做演示就不封装了)
        configuration.setJdbcDriver("com.mysql.cj.jdbc.Driver");
        configuration.setJdbcUsername("root");
        configuration.setJdbcPassword("root");
        configuration.setJdbcUrl("jdbc:mysql://localhost:3306/flowable_learn?serverTimezone=UTC");

        // 如果数据库中的表结构不存在就新建
        configuration.setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE);
        // 通过ProcessEngineConfiguration构建我们需要的processEngine对象
        ProcessEngine processEngine = configuration.buildProcessEngine();
        System.out.println("processEngine"   processEngine);
    }

    ProcessEngineConfiguration configuration = null;

    @Before
    public void before(){
        /*配置数据库设置*/
        configuration = new StandaloneInMemProcessEngineConfiguration();
        configuration.setJdbcDriver("com.mysql.cj.jdbc.Driver");
        configuration.setJdbcUsername("root");
        configuration.setJdbcPassword("root");
        configuration.setJdbcUrl("jdbc:mysql://localhost:3306/flowable_learn?serverTimezone=UTC");
        // 如果数据库中的表结构不存在就新建
        configuration.setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE);
    }

    /**
     * 部署流程
     * */
    @Test
    public void testDeploy(){
        // 1.获取ProcessEngine对象
        ProcessEngine processEngine = configuration.buildProcessEngine();
        // 2.获取RepositoryService
        RepositoryService repositoryService = processEngine.getRepositoryService();
        // 3.完成流程的部署操作
        Deployment deploy = repositoryService.createDeployment()
                .addClasspathResource("holiday-request.bpmn20.xml")
                .name("请求流程")
                .deploy();

        System.out.println("deploy.getId():"   deploy.getId());
        System.out.println("deploy.getName():"   deploy.getName());
    }

    /**
     * 查询流程定义的信息
     * */
    @Test
    public void testDeployQuery(){
        // 获取ProcessEngine对象
        ProcessEngine processEngine = configuration.buildProcessEngine();
        // 获取RepositoryService资源管理服务
        RepositoryService repositoryService = processEngine.getRepositoryService();


        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
                // deploymentId要查找现有的id(可以去数据库中查看deployment中查看),否则会报空指针异常
                .deploymentId("15001")
                .singleResult();

        System.out.println("processDefinition.getDeploymentId():"   processDefinition.getDeploymentId());
        System.out.println("processDefinition.getName():"   processDefinition.getName());
        System.out.println("processDefinition.getDescription():"   processDefinition.getDescription());
        System.out.println("processDefinition.getId():"   processDefinition.getId());
    }

    /**
     * 删除流程定义
     * */
    @Test
    public void testDeleteDeploy(){
        // 获取ProcessEngine对象
        ProcessEngine processEngine = configuration.buildProcessEngine();
        // 获取RepositoryService资源管理服务
        RepositoryService repositoryService = processEngine.getRepositoryService();

        // 删除部署的流程(第一个参数是id,如果部署的流程启动了就不允许删除了;第二是参数是级联删除,若为true,则若流程启动了,相关的任务会一并被删除)
        repositoryService.deleteDeployment("5001", true);
    }

    /**
     * 启动流程实例
     * */
    @Test
    public void testRunProcess(){
        ProcessEngine processEngine = configuration.buildProcessEngine();

        // 我们需要通过RuntimeService来启动流程实例
        RuntimeService runtimeService = processEngine.getRuntimeService();
        //构建流程变量
        Map<String, Object> variables = new HashMap<>();
        variables.put("employee", "张三");
        variables.put("nrOfHolidays", "3");
        variables.put("description", "工作累了,出去玩玩");

        // 启动流程实例
        ProcessInstance holidayRequest = runtimeService.startProcessInstanceByKey("holidayRequest", variables);
        System.out.println("holidayRequest.getProcessDefinitionId():"   holidayRequest.getProcessDefinitionId());
        System.out.println("holidayRequest.getActivityId():"   holidayRequest.getActivityId()); // 当前活跃
        System.out.println("holidayRequest.getId():"   holidayRequest.getId());
    }

    /**
     * 查询任务
     * */
    @Test
    public void testQueryTask(){
        ProcessEngine processEngine = configuration.buildProcessEngine();
        TaskService taskService = processEngine.getTaskService();
        List<Task> list = taskService.createTaskQuery()
                .processDefinitionKey("holidayRequest") // 指定查询的流程编程
                .taskAssignee("manager") // 查询这个任务的处理人
                .list();

        for (Task task: list) {
            System.out.println("task.getProcessDefinitionId():"   task.getProcessDefinitionId());
            System.out.println("task.getName():"   task.getName());
            System.out.println("task.getAssignee():"   task.getAssignee());
            System.out.println("task.getDescription():"   task.getDescription());
            System.out.println("task.getId():"   task.getId());
        }
    }

    /**
     * 执行任务
     * */
    @Test
    public void testCompleteTask(){
        ProcessEngine processEngine = configuration.buildProcessEngine();
        TaskService taskService = processEngine.getTaskService();
        Task task = taskService.createTaskQuery()
                .processDefinitionKey("holidayRequest")
                .taskAssignee("manager") //指定是经理
                .singleResult();

        // holiday-request.bpmn20.xml中${!approved}表示走拒绝策略,我们这里传一个${!approved}
        Map<String, Object> map = new HashMap<>();
        map.put("approved", false);

        // 完成任务
        taskService.complete(task.getId(), map);
    }

    /**
     * 获取流程任务的历史数据
     * */
    @Test
    public void testHistory(){
        ProcessEngine processEngine = configuration.buildProcessEngine();
        HistoryService historyService = processEngine.getHistoryService();

        List<HistoricActivityInstance> list = historyService.createHistoricActivityInstanceQuery()
                .processDefinitionId("holidayRequest:1:17503") // 从act_hi_actinst中获取
                .finished() // 查询的历史记录的状态是已完成
                .orderByHistoricActivityInstanceEndTime().asc() //指定排序的字段和顺序
                .list();

        for (HistoricActivityInstance history: list) {
            System.out.println(history.getActivityName()   ":"   history.getAssignee()   "--"   history.getActivityId()   ":"   history.getDurationInMillis()   "毫秒");
        }
    }

}
学新通

五、Flowable UI应用

1、安装

查看官网,可以看到有各种工具安装地址
学新通
由于官网的Flowable 6显示30天试用,就从百度找了flowable-6.7.2:https://blog.csdn.net/newposte/article/details/124329777,解压完如下
学新通
下载一个tomcat,我们把flowable-6.7.2里面的两个war包丢到tomcat的webapps里面去
学新通
学新通
我们找到startup.bat,运行它
学新通
然后发现有乱码
学新通
这时我们需要修改一下配置文件
学新通
学新通

java.util.logging.ConsoleHandler.encoding = GBK

再次启动startup.bat,发现乱码问题解决了
学新通
回到tomcat的webapp中查看,发现多出两个flowable文件
学新通
到这里我们就可以运行了,输入网址http://localhost:8080/flowable-ui
学新通
初始密码为 admin test,我们登录进去查看
学新通
这里就对应简介里面的几种应用
学新通

2、任务应用程序

创建流程
学新通
学新通
学新通
学新通
学新通
学新通
部署流程
点击右上角的一键导出按钮
学新通
然后文件就会被下载下来
学新通
然后我们复制这个文件到idea里,可以看到代码已经生成好了
学新通
代码
然后我们根据这个xml再书写一次代码,我们把Test01的代码全部复制,修改名称为TestMyHolidayUI
修改如下地方
学新通
然后我们运行部署流程方法,发现报错找不到我们新加进来的xml,我们删掉target再运行部署流程方法,让他生成新的target
学新通

如上图,在成功运行的同时就说明新的target生成好了,然后我们到数据库中查看
学新通

学新通
我们发现task表里面还没有东西,我们来运行testRunProcess方法,记得修改如下地方为procdef表中的数据且修改方法为ById
学新通
学新通
回到表中发现有数据了
学新通

3、建模器应用程序
4、管理员应用程序
5、身份管理应用程序

学新通
学新通
学新通
学新通
还可以添加、设置分组
学新通

六级标题

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhgakbkb
系列文章
更多 icon
同类精品
更多 icon
继续加载