工作流技术(WorkFlow)
什么是工作流#
1.使用编程语言完成一套固定的审批流程#
例如请假审批流程
订单配送流程
入职,辞职审批流程
2.使用场景#
业务类:合同审批流程、订单处理流程、出入库审批流程等。
行政类:请假流程、出差流程、用车流程、办公用品申请流程等。
财务类:报销流程、支付流程等。
客户服务类:售后跟踪、客户投诉等。
常见软件
-
尤其在OA,ERP,CRM软件中使用较多
-
OA
-
办公自动化(Office Automation)
-
-
ERP
-
企业资源计划即 ERP (Enterprise Resource Planning)
-
-
CRM
-
客户关系管理(Customer Relationship Management)
-
-
工作流中的核心三要素#
-
流程名称
-
流程绑定业务id
-
各流程负责人
官网(https://www.activiti.org/)#
activiti#
-
Activiti 是一个开源的工作流引擎,它实现了BPMN 2.0规范,可以发布设计好的流程定义,并通过api进行流程调度
-
BPM,Business Process Management 即业务流程管理) 的创建者 Tom Baeyens 离开 JBoss 之后建立的项目
-
BPMN 2.0其实也是一种类似于xml和html的一种标记语言,就是使用bpmn的规范来定义画流程图,最终形成一个bpmn文件
Springboot集成Activiti #
1.父工程pom下添加#
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-spring-boot-starter</artifactId>
<version>7.1.0.M6</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
2.注意: activiti7与spring security 强耦合因此两个依赖 必须都得引入 #
3.yml中spring节点下增加配置#
spring:
autoconfigure:
exclude:
- org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration
activiti:
#是否让activiti自动创建所有的历史表
history-level: full
#是否需要使用历史表,默认false不使用,而配置true是使用历史表
db-history-used: true
#流程自动部署,关闭,需要手动部署流程 服务启动的时候自动检查resources目录下的bpmn文件 如果为true自动部署流程
check-process-definitions: false
#关闭启动服务自动框架部署
deployment-mode: never-fail
4.集成好之后activiti会自动 再项目连接的MySQL数据库下创建25张表 #
Activiti开发流程 #
1.画流程图模型#
遵守BPMN的流程规范,使用BPMN的流程定义工具,通过 流程符号 把整个业务流程定义出来,将流程定义文件字节流保存到模型数据表中(Model)。每一个流程图都是一个.bpmn文件
2.部署流程定义#
加载画好的流程定义文件,将它转换成流程定义数据(ProcessDefifinition),保存到流程定义数据表中
3.启动流程 #
生成流程实例数据(ProcessInstance),生成第1个节点的任务数据(Task)
4.处理人审批流程节点任务 #
完成任务审批,生成审批结果,生成下一节点任务数据。直至满足条件,流程走到结束节点。
流程图模型中的各种符号 #
1.事件event符号#
-
开始事件(Start Event):表示流程的起点,通常用于触发流程的启动。
-
中间事件(Intermediate Event):发生在流程中间的事件,可以根据需要划分为多种类型,如定时器事件、消息事件、信号事件等。
-
结束事件(End Event):表示流程的结束点,通常用于触发流程的结束。
2.活动activity符号 #
-
任务(Task)是最基本的活动类型,表示一个简单的、可执行的工作单元
-
常见符号
-
1. 用户任务(User Task):表示需要由具体用户来执行的任务。在流程中,当流程执行到用户任务节点时,会生成一个待办任务,需要指定具体的执行人来完成任务。
-
2. 服务任务(Service Task):通过调用外部服务或执行业务逻辑来完成任务的一种任务类型。可以调用Java类、Web服务、REST接口等来执行具体的任务操作。
-
3. 接收任务(Receive Task):表示等待外部触发的任务,当接收到外部的信号或消息时,流程会继续执行下一步。可以用于等待外部系统的通知或事件触发。
-
4. 发送任务(Send Task):表示发送消息或触发事件的任务类型。可以发送消息给外部系统或触发特定的事件,用于与外部系统进行交互。
-
5. 业务规则任务(Business Rule Task):表示执行业务规则来完成任务的一种任务类型。可以通过规则引擎执行事先定义好的业务规则,用于根据特定条件做出决策。
-
3.网关Gateway符号 #
-
用于处理流程中的决策
-
1. 排他网关(Exclusive Gateway):也称为XOR网关或基于数据的排他网关,用于在流程中创建决策点。当执行到达排他网关时,所有出口顺序流会按照它们定义的顺序进行计算。条件计算为true的顺序流会被选择用于继续流程。
-
相当于if-else只走一个分支
-
-
2. 包容网关(Inclusive Gateway):也称为AND网关或包容性决策网关,用于在流程中创建平行的路径。当执行到达包容网关时,所有出口顺序流同时进行计算,并且至少要有一个条件计算为true的顺序流被选择用于继续流程。
-
只需要满足一个条件
-
-
3. 综合网关(Complex Gateway):用于模拟复杂的同步行为。通过表达式激活条件描述精确的行为。
-
4. 基于事件的网关(Event-based Gateway):基于事件的网关代表流程中的一个分支点,其中遵循网关的替代路径基于发生的事件,而不是使用流程数据对表达式的评估。
-
5. 并行网关(Parallel Gateway):用于同步(组合)并行流并创建并行流。
具体流程 #
1.部署流程#
把xml文件和图片写入到数据库当中
Java类
RepositoryService
创建部署
createDeployment
删除部署
deleteDeployment
涉及表
ACT_RE_PROCDEF 新增数据: 流程定义数据
ACT_RE_DEPLOYMENT 新增数据: 流程部署数据
ACT_GE_BYTEARRAY 新增数据:将当前流程图绑定到此流程定义部署数据上
ACT_RE_MODEL 更新部署id
2.启动流程 #
读取部署好到表中的流程数据开启流程,创建流程审批模板实例
Java类
RuntimeService
startProcessInstanceByKey(String processDefinitionKey, String businessKey)
参数:
部署好的流程名称选模板
唯一业务主键
涉及到的表
● act_hi_actinst 流程实例执行历史
● act_hi_identitylink 流程的参与用户历史信息
● act_hi_procinst 流程实例历史信息
● act_hi_taskinst 流程任务历史信息
● act_ru_execution 流程执行信息
● act_ru_identitylink 流程的参与用户信息
● act_ru_task 任务信息
3.操作流程 #
Java类
TaskService
负责人查询待办任务
TaskService
查询单条代办查询
singleResult
查询全部代办任务
list
分页查询代办任务
listPage
条件查询
根据流程名称查询
processDefinitionKey
根据负责人查询
taskAssignee
根据流程绑定业务id查询
processInstanceBusinessKey
模糊查询
方法中带like
精确查询
方法中带equals
范围查询
方法中带after,before,group,in,between等
完成
TaskSercive
complete(String taskId, Map<String,Object> variables, boolean localScope)
可结束当前节点流程,标记为已完成,并且流程会自动开启下一个节点的任务。同时在结束时还可以把填写的数据,作为流程变量传递到下一个流程中
参数
任务id
携带变量
是否为全局变量,是则为全流程可见
拒绝
RuntimeService
deleteProcessInstance(String processInstanceId, String deleteReason);
TaskSercive
deleteTask
查询历史
HistoryService
processInstanceBusinessKey(String processInstanceBusinessKey)
taskId(String taskId)
taskAssignee(String taskAssignee) | taskAssigneeLike(String taskAssignee)
finished()
unfinished()
orderByHistoricTaskInstanceEndTime().desc()
taskName(String var1) | taskNameLike(String var1)
includeProcessVariables()
processVariableValueEquals(String variableName, Object variableValue)
processVariableValueNotEquals(String variableName, Object variableValue)
processVariableValueGreaterThan(String name, Object value)
processVariableValueLessThan(String name, Object value)
createHistoricTaskInstanceQuery
list()
业务流程梳理 #
1.在web包resources下新建bpmn目录#
看看自己是否装了这个插件
新建bpmn.xml文件
2.右击通过你安装的插件中打开#
3.开始画流程图#
4.创建完成导出png图片#
5.流程测试创建#
package com.zzyl;
import lombok.extern.slf4j.Slf4j;
import org.activiti.engine.HistoryService;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.task.Task;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Slf4j
@SpringBootTest
public class TestActiviti {
@Resource
private RepositoryService repositoryService;
@Resource
private RuntimeService runtimeService;
@Resource
private TaskService taskService;
@Resource
private HistoryService historyService;
@Test
public void create() {
//1.创建部署对象
//2.读取要存在mysql中的bpmn文件和图片
//3.部署
repositoryService.createDeployment()
.addClasspathResource("bpmn/学生请假流程.bpmn20.xml")
.addClasspathResource("bpmn/diagram.png")
//name一般和bpmn文件名称一样
.name("学生请假流程")
.deploy();
}
@Test
public void delete() {
//级联删除所有关联 表数据
repositoryService.deleteDeployment("63f13c79-9407-11ee-adad-f0d7afd01b33",true);
}
@Test
public void startProcess() {
runtimeService.startProcessInstanceByKey("学生请假流程", "123455");
}
@Test
public void queryRuntimeProcess() {
List<Task> list = taskService.createTaskQuery().taskAssignee("张三")
.list();
list.forEach(v -> {
log.info("获取任务执行的id:{}", v.getId());
log.info("获取代办人:{}", v.getAssignee());
log.info("获取业务id:{}", v.getBusinessKey());
});
}
@Test
public void completeApplicationTable() {
//填写申请表并且完成申请表的代办
HashMap<String, Object> map = new HashMap<>();
map.put("username", "张三");
map.put("reason", "中秋节回家吃月饼");
map.put("startTime", "2024-09-09");
map.put("endTime", "2024-09-20");
map.put("days", 5);
taskService.complete("3ba73dde-7279-11ef-8e5d-62df74cf4810",map,true);
}
@Test
public void processNextComplete() {
Task task = taskService.createTaskQuery().taskAssignee("l").singleResult();
//获取任务节点传递的变量
Map<String, Object> variables = taskService.getVariables(task.getId());
log.info("代办任务id={}申请内容={}代办人={}", task.getId(), variables, task.getAssignee());
//同意
HashMap<String, Object> okReason = new HashMap<>();
okReason.put("reason", "同意");
okReason.put("remark", "但是课要补回来");
taskService.complete(task.getId(), okReason, true);
// HashMap<String, Object> map = new HashMap<>();
// map.put("reason","拒绝");
// map.put("remark","项目周期长不能让你猖狂");
//
// runtimeService.deleteProcessInstance(task.getProcessInstanceId(),"请假时间过长");
}
@Test
public void queryHistoryProcess() {
List<HistoricProcessInstance> list = historyService.createHistoricProcessInstanceQuery()
.finished().list();
list.forEach(v -> {
log.info("获取业务id={},获取流程名称={},获取流程开始时间={},获取流程结束时间={},拒绝原因={}",
v.getBusinessKey(), v.getProcessDefinitionName(),v.getStartTime(),v.getEndTime(),v.getDeleteReason());
});
}
@Test//查询全部部署信息
public void listDeployments() {
List<Deployment> deployments = repositoryService.createDeploymentQuery().list();
for (Deployment deployment : deployments) {
System.out.println("Deployment ID: " + deployment.getId());
System.out.println("Deployment Name: " + deployment.getName());
}
}
}
6.四个DI注入的作用#
在 Activiti 中,
RepositoryService
、RuntimeService
、TaskService
和HistoryService
是四个核心服务接口,分别用于不同的操作和功能。下面是它们的作用和常见用途:1.
RepositoryService
作用: 负责管理流程定义和部署相关的操作。
常见方法:
- 部署流程:
createDeployment()
、deploy()
— 部署新的流程定义。- 删除部署:
deleteDeployment(deploymentId, cascade)
— 删除指定的部署,cascade
参数决定是否级联删除相关数据。- 查询流程定义:
createProcessDefinitionQuery()
— 查询流程定义的列表或特定定义。- 获取流程定义资源:
getProcessDiagram()
— 获取流程图的资源。使用场景:
- 部署新的流程定义到引擎中。
- 查询、删除已部署的流程定义。
- 更新和管理流程模型。
2.
RuntimeService
作用: 负责管理正在运行的流程实例和任务相关的操作。
常见方法:
- 启动流程实例:
startProcessInstanceByKey(processDefinitionKey, businessKey)
— 启动新的流程实例。- 获取流程实例:
createProcessInstanceQuery()
— 查询正在运行的流程实例。- 删除流程实例:
deleteProcessInstance(processInstanceId, reason)
— 删除正在运行的流程实例。使用场景:
- 启动新的流程实例以执行业务流程。
- 查询和管理正在运行的流程实例。
- 结束或取消正在运行的流程实例。
3.
TaskService
作用: 负责管理任务的操作,主要涉及任务的创建、查询、分配和完成。
常见方法:
- 创建任务查询:
createTaskQuery()
— 查询任务的列表或特定任务。- 完成任务:
complete(taskId, variables)
— 完成指定的任务,并可传递流程变量。- 分配任务:
setAssignee(taskId, userId)
— 为任务指定处理人。使用场景:
- 查询当前待办任务和处理任务。
- 完成任务并更新流程变量。
- 分配和重新分配任务。
4.
HistoryService
作用: 负责管理历史数据和流程实例的历史记录。
常见方法:
- 查询历史流程实例:
createHistoricProcessInstanceQuery()
— 查询已完成的流程实例。- 查询历史任务:
createHistoricTaskInstanceQuery()
— 查询已完成的任务历史记录。- 获取历史数据:
getHistoricVariableInstance(variableId)
— 获取历史变量的值。使用场景:
- 查询和分析已完成的流程实例和任务。
- 获取流程执行的历史数据和相关信息。
- 监控和审计业务流程的历史记录。
总结
RepositoryService
: 用于部署、管理和删除流程定义及相关资源。RuntimeService
: 用于启动、查询和管理正在运行的流程实例。TaskService
: 用于处理任务,包括创建查询、完成任务和任务分配。HistoryService
: 用于查询和管理流程实例和任务的历史记录。这些服务接口共同帮助你在 Activiti 引擎中完成从流程定义、运行到历史记录的全面管理。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· .NET10 - 预览版1新功能体验(一)