文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Spring Boot + flowable 完美结合,快速实现工作流

2024-12-01 19:48

关注

1. flowable-ui部署运行

flowable-6.6.0 运行 官方demo。

参考文档:https://flowable.com/open-source/docs/bpmn/ch14-Applications/。

注意:需要将java驱动jar(mysql-connector-java-5.1.45.jar​)复制到 apache-tomcat-9.0.37\webapps\flowable-rest\WEB-INF\lib。

这样创建的流程后端程序就能直接使用。

2. 绘制流程图

根据业务需要在 flowable-ui>APP.MODELER里面绘制流程图,示例如上图。先解释一些概念。

简单的工作流大概就这些元素(还有很多这里就不扩展了)。下面描述一下工作流是如何流动的。

首先启动了工作流后,由【开始】节点自动流向【学生】节点,等待该任务执行。任务被分配的学生用户执行后流向 【老师】节点,再次等待该任务执行。被分配的老师用户执行后流向 【网关】,网关以此检查每个出口,流向符合条件的任务,比如这里老师执行任务时是同意,就流向【校长】节点,等待该任务执行。执行后跟老师类似,同意后就流向【结束】节点,整个流程到此结束。

绘图细节:

(1)保留流程模型。

(2)顺序流可以设置流条件来限制流动,比如上面的网关出口就设置了条件。

(3)任务需要分配任务的执行用户,可以分配到候选组,也可以直接分配到候选人。

最后导出工作流文件。

文件内容:

<?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-insmtece" 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="leave_approval" name="请假审批" isExecutable="true">
<startEvent id="start" name="开始" flowable:initiator="startuser" flowable:formFieldValidation="true">startEvent>
<userTask id="stu_task" name="学生" flowable:candidateGroups="stu_group" flowable:formFieldValidation="true">userTask>
<sequenceFlow id="flow1" sourceRef="start" targetRef="stu_task">sequenceFlow>
<userTask id="te_task" name="老师" flowable:candidateGroups="te_group" flowable:formFieldValidation="true">userTask>
<exclusiveGateway id="getway1" name="网关1">exclusiveGateway>
<userTask id="mte_task" name="校长" flowable:candidateGroups="mte_group" flowable:formFieldValidation="true">userTask>
<exclusiveGateway id="getway2" name="网关2">exclusiveGateway>
<endEvent id="end" name="结束">endEvent>
<sequenceFlow id="flow1" name="请假" sourceRef="stu_task" targetRef="te_task" skipExpression="${command=='agree'}">sequenceFlow>
<sequenceFlow id="flow3_1" name="同意" sourceRef="getway1" targetRef="mte_task">
<conditionExpression xsi:type="tFormalExpression">[CDATA[${command=='agree'}]]>conditionExpression>
sequenceFlow>
<sequenceFlow id="flow2" name="审批" sourceRef="te_task" targetRef="getway1">sequenceFlow>
<sequenceFlow id="flow3_2" name="拒绝" sourceRef="getway1" targetRef="stu_task">
<conditionExpression xsi:type="tFormalExpression">[CDATA[${command=='refuse'}]]>conditionExpression>
sequenceFlow>
<sequenceFlow id="flow4" name="审批" sourceRef="mte_task" targetRef="getway2">sequenceFlow>
<sequenceFlow id="flow4_1" name="同意" sourceRef="getway2" targetRef="end" skipExpression="${command=='free'}">
<conditionExpression xsi:type="tFormalExpression">[CDATA[${command=='agree'}]]>conditionExpression>
sequenceFlow>
<sequenceFlow id="flow4_2" name="拒绝" sourceRef="getway2" targetRef="stu_task">
<conditionExpression xsi:type="tFormalExpression">[CDATA[${command=='refuse'}]]>conditionExpression>
sequenceFlow>
process>
<bpmndi:BPMNDiagram id="BPMNDiagram_leave_approval">
这里先省略
bpmndi:BPMNDiagram>
definitions>

(4)bpmn文件导入。

如果需要,可以把这个流程文件下载下来,直接导入使用。

3. 后台项目搭建

后台项目基于jdk8,使用springboot框架。

spring 版本

<parent>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-parentartifactId>
<version>2.3.0.RELEASEversion>
<relativePath/>
parent>

项目依赖pom.xml

<dependency>
<groupId>org.flowablegroupId>
<artifactId>flowable-spring-boot-starterartifactId>
<version>6.6.0version>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>5.1.45version>
dependency>

项目配置application.yml

spring:
datasource:
url: jdbc:mysql://localhost:3306/flowable?useSSL=false&characterEncoding=UTF-8&serverTimezone=GMT%2B8
driver-class-name: com.mysql.jdbc.Driver
username: root
password: 123456

4. 数据库

(1)Flowable的所有数据库表都以ACT_开头。第二部分是说明表用途的两字符标示符。服务API的命名也大略符合这个规则。

(2)ACT_RE_: 'RE’代表repository。带有这个前缀的表包含“静态”信息,例如流程定义与流程资源(图片、规则等)。

(3)ACT_RU_: 'RU’代表runtime。这些表存储运行时信息,例如流程实例(process instance)、用户任务(user task)、变量(variable)、作业(job)等。Flowable只在流程实例运行中保存运行时数据,并在流程实例结束时删除记录。这样保证运行时表小和快。

(4)ACT_HI_: 'HI’代表history。这些表存储历史数据,例如已完成的流程实例、变量、任务等。

(5)ACT_GE_: 通用数据。在多处使用。

1)通用数据表(2个)

2)历史表(8个,HistoryService接口操作的表)

3)用户相关表(4个,IdentityService接口操作的表)

4)流程定义、流程模板相关表(3个,RepositoryService接口操作的表)

5)流程运行时表(6个,RuntimeService接口操作的表)

5. 流程引擎API与服务

引擎API是与Flowable交互的最常用手段。总入口点是ProcessEngine。

接下来使用之前的请假流程图,上代码:

代码

import lombok.extern.slf4j.Slf4j;
import org.flowable.engine.HistoryService;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.engine.repository.Deployment;
import org.flowable.engine.repository.ProcessDefinition;
import org.flowable.engine.runtime.Execution;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.idm.api.Group;
import org.flowable.idm.api.User;
import org.flowable.task.api.Task;
import org.flowable.task.api.history.HistoricTaskInstance;
import org.springframework.beans.factory.annotation.Autowired;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipInputStream;


@Slf4j
public class TestFlowable {

@Autowired
private RepositoryService repositoryService;

@Autowired
private RuntimeService runtimeService;

@Autowired
private HistoryService historyService;

@Autowired
private org.flowable.engine.TaskService taskService;

@Autowired
private org.flowable.engine.IdentityService identityService;

public void createDeploymentZip() {


try {
File zipTemp = new File("f:/leave_approval.bpmn20.zip");
ZipInputStream zipInputStream = new ZipInputStream(new FileInputStream(zipTemp));
Deployment deployment = repositoryService
.createDeployment()
.addZipInputStream(zipInputStream)
.deploy();
log.info("部署成功:{}", deployment.getId());
} catch (FileNotFoundException e) {
e.printStackTrace();
}


List<ProcessDefinition> list = repositoryService.createProcessDefinitionQuery().processDefinitionKey("leave_approval").list();
List<ProcessDefinition> pages = repositoryService.createProcessDefinitionQuery().processDefinitionKey("leave_approval").listPage(1, 30);


String processDefinitionKey = "leave_approval";//流程定义的key,对应请假的流程图
String businessKey = "schoolleave";//业务代码,根据自己的业务用
Map<String, Object> variablesDefinition = new HashMap<>();//流程变量,可以自定义扩充
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(processDefinitionKey, businessKey, variablesDefinition);
log.info("启动成功:{}", processInstance.getId());


List<Execution> executions = runtimeService.createExecutionQuery().processDefinitionKey("leave_approval").list();
List<Execution> executionPages = runtimeService.createExecutionQuery().processDefinitionKey("leave_approval").listPage(1, 30);
// runtimeService.deleteProcessInstance(processInstanceId, deleteReason); //删除实例


String candidateGroup = "stu_group"; //候选组 xml文件里面的 flowable:candidateGroups="stu_group"
List<Task> taskList = taskService.createTaskQuery().taskCandidateGroup(candidateGroup).orderByTaskCreateTime().desc().list();
for (Task task : taskList) {
// 申领任务
taskService.claim(task.getId(), "my");
// 完成
taskService.complete(task.getId());
}


String candidateGroupTe = "te_group"; //候选组 xml文件里面的 flowable:candidateGroups="te_group"
List<Task> taskListTe = taskService.createTaskQuery().taskCandidateGroup(candidateGroupTe).orderByTaskCreateTime().desc().list();
for (Task task : taskListTe) {
// 申领任务
taskService.claim(task.getId(), "myte");
// 完成
Map<String, Object> variables = new HashMap<>();
variables.put("command","agree"); //携带变量,用于网关流程的条件判定,这里的条件是同意
taskService.complete(task.getId(), variables);
}


// 历史流程实例
List<HistoricProcessInstance> historicProcessList = historyService.createHistoricProcessInstanceQuery().processDefinitionKey("leave_approval").list();
// 历史任务
List<HistoricTaskInstance> historicTaskList = historyService.createHistoricTaskInstanceQuery().processDefinitionKey("leave_approval").list();
// 实例历史变量 , 任务历史变量
// historyService.createHistoricVariableInstanceQuery().processInstanceId(processInstanceId);
// historyService.createHistoricVariableInstanceQuery().taskId(taskId);

// *****************************************************分隔符********************************************************************
// *****************************************************分隔符********************************************************************
// 可能还需要的API
// 移动任务,人为跳转任务
// runtimeService.createChangeActivityStateBuilder().processInstanceId(processInstanceId)
// .moveActivityIdTo(currentActivityTaskId, newActivityTaskId).changeState();

// 如果在数据库配置了分组和用户,还会用到
List<User> users = identityService.createUserQuery().list(); //用户查询,用户id对应xml 里面配置的用户
List<Group> groups = identityService.createGroupQuery().list(); //分组查询,分组id对应xml 里面配置的分组 如 stu_group,te_group 在表里是id的值

// 另外,每个查询后面都可以拼条件,内置恁多查询,包括模糊查询,大小比较都有
}
}

6. 参考资料

分享牛Flowable文档汉化:https://github.com/qiudaoke/flowable-userguide

猫七姑娘 flowable-6.6.0 运行官方 demo

华格瑞沙 https://www.cnblogs.com/yangjiming/p/10938515.html

来源:码猿技术专栏内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯