flowable最贴心的入门案例,讲清涉及的关键表

flowable最贴心的入门案例,讲清涉及的关键表

flowable基本配置

  1. 导入如下jar包,包括flowable的核心包,日志包以及mysql包
    <dependency>
      <groupId>org.flowable</groupId>
      <artifactId>flowable-engine</artifactId>
      <version>6.3.0</version>
    </dependency>
    <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>
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>8.0.21</version>
    </dependency>

在resources中新建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
  1. 获取流程引擎
    代码如下所示,通过简单的方式进行数据库配置和流程引擎的获取,后续的各种操作都依赖于流程引擎。
ProcessEngineConfiguration cfg = new StandaloneProcessEngineConfiguration()
                .setJdbcUrl("jdbc:mysql://localhost:3306/flowable-learn?serverTimezone=UTC&nullCatalogMeansCurrent=true")
                .setJdbcUsername("root")
                .setJdbcPassword("root")
                .setJdbcDriver("com.mysql.cj.jdbc.Driver")
                .setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_DROP_CREATE);
        ProcessEngine processEngine = cfg.buildProcessEngine();

配置数据库时有四种配置,如下

    public static final String DB_SCHEMA_UPDATE_FALSE = "false";
    public static final String DB_SCHEMA_UPDATE_CREATE = "create";
    public static final String DB_SCHEMA_UPDATE_CREATE_DROP = "create-drop";
    public static final String DB_SCHEMA_UPDATE_DROP_CREATE = "drop-create";
  1. DB_SCHEMA_UPDATE_FALSE = "false"
    含义:不自动更新数据库模式。即,应用程序启动时,数据库模式不会发生任何改变。如果数据库中表结构与实体类(或模型)不一致,应用程序将抛出异常,要求手动处理。
    使用场景:适用于生产环境,避免在启动时自动修改数据库结构,确保数据库的稳定性。
  2. DB_SCHEMA_UPDATE_CREATE = "create"
    含义:每次应用启动时,都会根据实体类创建新的数据库表。通常会删除现有的表并重新创建。这意味着如果表已经存在,它们将被删除并重新创建(不会保留数据)。
    使用场景:适用于开发环境或者首次部署时,用于生成表结构。如果不关心数据丢失,可以使用这个选项。
  3. DB_SCHEMA_UPDATE_CREATE_DROP = "create-drop"
    含义:在应用启动时创建数据库表,在应用停止时删除数据库表。这个选项会在应用的生命周期内创建表,但在应用停止时会删除表,因此适合用于开发、测试或临时环境。
    使用场景:适用于测试和开发环境,当你不需要持久存储数据库数据时。
  4. DB_SCHEMA_UPDATE_DROP_CREATE = "drop-create"
    含义:在应用启动时删除现有的数据库表,并根据实体类重新创建表。不同于 create-drop,这个选项不会在应用停止时删除表。它只会在应用启动时删除和创建表,但不影响应用的生命周期。
    使用场景:适用于开发过程中,当你希望每次启动时都从头开始,重建表结构,但不希望在应用停止时丢失表。

定义一个审核流程

如图,通常审核流程包括如下结构,开始节点、结束节点和中间具体执行人的节点,另外有一些形式的审核流程不包括申请人的环节,直接绘制审核流程,通常情况下包含申请人更加合理。并且二者的在操作上并无太大差异,具体可以在了解flowable的工作原理后自行辨别。
img
如下是对应的xml文件的关键信息,其中包括流程id,流程名称,流程分类,这里还可以定义流程描述和其他的属性信息

 <process id="flow_z81n3ymf" name="测试流程1" flowable:processCategory="type1">
    <documentation>测试流程1.</documentation>
    <extensionElements>
      <flowable:properties>
        <flowable:property name="expro1" value="value1" />
        <flowable:property name="expro2" value="value2" />
      </flowable:properties>
    </extensionElements>
    <startEvent id="start_event" name="开始">
      <outgoing>Flow_03y5jhz</outgoing>
    </startEvent>
    <userTask id="Activity_0egx7q1" name="申请人">
      <incoming>Flow_03y5jhz</incoming>
      <outgoing>Flow_1wluipz</outgoing>
    </userTask>
    <userTask id="Activity_0ovnvli" name="一级处理人" flowable:assignee="1" flowable:userType="assignee" flowable:dataType="fixed">
      <incoming>Flow_1wluipz</incoming>
      <outgoing>Flow_1gldaiz</outgoing>
    </userTask>
    <userTask id="Activity_11blnld" name="二级处理人" flowable:assignee="1" flowable:userType="assignee" flowable:dataType="fixed">
      <extensionElements>
        <flowable:properties />
      </extensionElements>
      <incoming>Flow_1gldaiz</incoming>
      <outgoing>Flow_08pelnj</outgoing>
    </userTask>
    <endEvent id="Event_07og00d" name="结束">
      <incoming>Flow_08pelnj</incoming>
    </endEvent>
    <sequenceFlow id="Flow_03y5jhz" sourceRef="start_event" targetRef="Activity_0egx7q1" />
    <sequenceFlow id="Flow_1wluipz" sourceRef="Activity_0egx7q1" targetRef="Activity_0ovnvli" />
    <sequenceFlow id="Flow_1gldaiz" sourceRef="Activity_0ovnvli" targetRef="Activity_11blnld" />
    <sequenceFlow id="Flow_08pelnj" sourceRef="Activity_11blnld" targetRef="Event_07og00d" />
  </process>

部署一个审核流程

下面通过部署上文中的xml形式定义的审核流程,了解flowable中涉及到的表以及对应的关系

  1. 流程部署代码
    流程部署通过repositoryService进行,使用流程引擎processEngine获得。
        // 部署流程 获取RepositoryService对象
        RepositoryService repositoryService = processEngine.getRepositoryService();
        Deployment deployment = repositoryService.createDeployment()// 创建Deployment对象
                .addClasspathResource("测试流程1.bpmn20.xml") // 添加流程部署文件
                .name("部署名称")
                .category("部署分类")
                .deploy(); // 执行部署操作
		//设置流程定义类别
		ProcessDefinition definition = repositoryService.createProcessDefinitionQuery().deploymentId(deployment.getId()).singleResult();
		repositoryService.setProcessDefinitionCategory(definition.getId(), "type1");
				
  1. 流程部署具体过程
    通过查看相关日志,有如下信息。说明在部署时会插入四个对象,这里的对象id已经确定,所以后面再插入的时候可以先插入流程实例,再插入流程部署
    img
    下面根据日志中的insert语句分析具体流程
  • 首先,在ACT_RE_PROCDEF表插入流程定义相关数据,xml中的id,name,documentation(数据库中的DESCRIPTION_)都有对应字段,但CATEGORY_是默认分类,说明flowable:processCategory并不能直接映射到数据库中,可以通过API进行设置。
    img
    ACT_RE_PROCDEF表结构如下,SUSPENSION_STATE_中1表示部署,2表示挂起。
    img
  • 其次在ACT_RE_DEPLOYMENT表插入流程部署相关信息
    img
    img
  • 在ACT_GE_BYTEARRAY中插入部署流程的xml文件的byte数据,包括xml文件和图片形式的文件
    img
    img
    总结:流程部署时涉及三个表,其中部署表是最主要的表,流程定义表中关联部署表,并且流程信息的文件表也通过部署ID进行关联。

查看审核流程

有了上述分析,查看审核流程就很简单了,只是对上述表进行相关查询,可以自己实现,当然最好是使用flowable中的API进行。

//查询流程定义表
ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
                .deploymentId("1")
                .singleResult();
//查询流程部署表
Deployment deployment = repositoryService.createDeploymentQuery().deploymentId("1").singleResult();
//查询资源表,根据资源名称区分xml文件和图片文件
InputStream xml = repositoryService.getResourceAsStream(processDefinition.getDeploymentId(), processDefinition.getResourceName());
InputStream png = repositoryService.getResourceAsStream(processDefinition.getDeploymentId(), processDefinition.getDiagramResourceName());  

上述只能获取图片的二进制流,flowable提供了更加便捷的方式

ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().deploymentId(deployId).singleResult();
//获得图片流
DefaultProcessDiagramGenerator diagramGenerator = new DefaultProcessDiagramGenerator();
BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinition.getId());
//输出为图片
return diagramGenerator.generateDiagram(
				bpmnModel,
				"png",
				Collections.emptyList(),
				Collections.emptyList(),
				"宋体",
				"宋体",
				"宋体",
				null,
				1.0,
				false);

启动流程实例

启动流程实例需要使用runtimeService,样例代码如下:

//启动前可以设置流程启动的用户id
identityService.setAuthenticatedUserId(sysUser.getUserId().toString());
// 启动流程实例通过 RuntimeService 对象
RuntimeService runtimeService = processEngine.getRuntimeService();
// 构建流程变量
Map<String,Object> variables = new HashMap<>();
variables.put("employee","张三") ;// 谁申请请假
variables.put("nrOfHolidays",3); // 请几天假
variables.put("description","工作累了,想出去玩玩"); // 请假的原因
// 启动流程实例,第一个参数是流程定义的id
ProcessInstance processInstance = runtimeService
				.startProcessInstanceByKey("flow_z81n3ymf", variables);// 启动流程实例
// 输出相关的流程实例信息
System.out.println("流程定义的ID:" + processInstance.getProcessDefinitionId());
System.out.println("流程实例的ID:" + processInstance.getId());
System.out.println("当前活动的ID:" + processInstance.getActivityId());

上述代码很简单,下面分析下具体执行过程。在启动流程实例时,传入了涉及的参数,如在请假流程中的申请人、请假天数和理由,实际上可以传递任意参数,如果不想直接传入或业务有其他要求,可以另外新建申请表,才启动流程实例时传入申请表中记录的id即可,在需要信息时再根据记录id去查询记录。
启动流程实例涉及如下表插入操作
img
启动流程实例时,涉及到流程实例表和历史流程实例表两个插入
传入参数,涉及到参数表和历史参数表的插入,几条参数几个插入
流程从start圆圈开始启动,并进入第一个方块,涉及到两个历史活跃实例,分别是start圆圈的和第一个方块的
流程启动后,到第一个方块,会产生一个任务,涉及一个任务的插入
流程启动后,需要一个执行实例,涉及到执行实例的插入

  1. 具体操作中先向ACT_HI_VARINST表插入传递的数据,三条数据一起插入。
    img
    这是对应的表结构,主要包括流程实例ID,执行实例ID,任务实例ID,当前是流程实例的数据,因此任务ID为空
    img
  2. 向ACT_HI_TASKINST插入任务信息
    img
    关键信息包括流程定义ID,流程实例ID,执行实例ID,任务定义KEY等信息,还有业务相关信息,如办理人、开始时间、认领时间,在对任务进行操作时,任务历史信息都会跟着改变。
    img
  3. 历史流程实例插入
    img
    img
  4. 然后是历史活动的节点表
    img
    包括流程实例ID,执行实例ID等
    img
  5. 执行实例插入act_ru_execution,
    ACT_RU_EXECUTION表即运行时流程执行实例表。该表主要用于存储流程运行时的执行实例。流程启动时,会生成一个流程实例,以及相应的执行实例,流程实例和执行实例都存储在ACT_RU_EXECUTION表中。因此实行了两条插入。执行实例有个字段PARENT_ID_指向流程实例
    img
  6. 运行任务的插入
    img
    img
  7. 运行时数据插入 同历史数据插入
    img
    总结,启动一个任务涉及到上述7张表的操作,需要注意的是历史实例表是单独一张表,流程实例和流程执行在一张流程执行表中,开启一个流程实例会在流程实例表添加两条数据,流程执行的PARENT_ID_指向流程实例。

查看我的待执行的任务

流程已经启动了,卡在申请人的步骤,现在申请人需要查看他的任务,并进行相关处理。在我们这里,并没有指定申请人的任务执行人,一般来说启动一个流程实例时,同时会把申请人的环节执行掉,现在我们使用部署id来获得这个任务,通常是使用候选人或候选组进行查找。

TaskService taskService = processEngine.getTaskService();
Task task = taskService.createTaskQuery().deploymentId("1").singleResult();
System.out.println("task.getProcessDefinitionId() = " + task.getProcessDefinitionId());
System.out.println("task.getId() = " + task.getId());
System.out.println("task.getAssignee() = " + task.getAssignee());
System.out.println("task.getName() = " + task.getName());
HashMap<String, Object> map = new HashMap<>();
map.put("name","张三");
//taskService.addComment()审核时还可以添加评论
taskService.complete(task.getId(),map);

涉及到8个插入,3个更新,1个删除
img
完成后进入下一个方块,即插入新的任务,活跃节点,同时插入到历史任务,还有方块对应的历史活跃节点,更新执行实例的活跃节点到这个方块,删除执行完的任务,更新历史中这个任务和活跃节点的完成时间完成人等信息。
3插3更1删
添加了一条数据,涉及到数据和历史数据插入,这里的数据还是属于流程实例的,不是任务的,因此表中任务id为空。
2插
ACT_HI_IDENTITYLINK表即历史流程与身份关系表,其字段如下表所示。该表主要用于存储历史流程实例、任务实例与参与者之间的关联关系。
img
记录执行完的任务的执行人信息,和流程的参与人信息。
一个任务执行后会在历史表中记录执行人信息对应任务ID,和执行人信息对应执行实例
一个任务完成执行,在act_ru_identitylink中会存放执行人对应执行实例的记录
(这个就是记录执行人相关信息,在task中一般都有执行人,这个表的作用我暂时还不知道)
3插

继续执行任务

当前任务到了一级审核人,对应id为1,因此可以通过这个查询到任务,并执行。

最基本的操作就到这里,涉及到了关键的几张表,以及一些我觉得会忽略的细节,可以搭配贺波的深入Activit流程引擎以及flowable的官方文档https://www.flowable.com/open-source/docs/ 进行理解。上文如有错误,欢迎指正,谢谢。。

posted @   zsandyzw  阅读(199)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 上周热点回顾(3.3-3.9)
· AI 智能体引爆开源社区「GitHub 热点速览」
· 写一个简单的SQL生成工具
点击右上角即可分享
微信分享提示