目录
一、工作流
1.1、什么是工作流
1.2、工作流引擎
1.3、常见工作流引擎
二、 Activiti7概述
2.1、Activiti介绍
2.2、建模语言BPMN
2.3、 Activiti使用流程
三、 Activiti使用
3.1、部署流程工具
3.2、画出流程图并放入项目中
3.3、流程定义部署
3.4、启动流程实例
3.5、查询任务
3.6、处理当前任务与处理查询
3.7、流程实例
一、工作流
1.1、什么是工作流
工作流(Workflow),就是通过计算机对业务流程自动化执行管理。它主要解决的是“使在多个参与者之间按照某种预定义的规则自动进行传递文档、信息或任务的过程,从而实现某个预期的业务目标,或者促使此目标的实现”。通俗来讲,就是业务上一个完整的审批流程。**例如员工的请假,出差,外出采购,合同审核等等,这些过程,都是一个工作流。
1.2、工作流引擎
对于工作流的处理,如果采用原始的方式,我们需要拿着各种文件到各个负责人那里去签字,需要在多个部门之间不断审批,这种方式费时费力。而我们可以借助软件系统来协助我们处理这些审批流程,这样就出现了工作流系统,使用工作流系统后可以极大的提高工作效率。
在学习工作流的过程中,我们肯定看到过这个模型:填写请假单->部门经理审批->总经理审批->人事备案。
(1)要实现上述的流程,我们自己可以通过字段标识来实现这个审批效果,在业务表中加个字段,比如填写请假单用1标识,部门经理用2标识,总经理用3标识,人事备案用4标识,好像看起来没啥问题,也实现了审批效果。可是一旦我们的流程出现了变化,这个时候我们就需要改动我们的代码了,这显然是不可取的,那么有没有专业的方式来实现工作流的管理呢?并且可以做到业务流程变化之后,我们的程序可以不用改变,如果可以实现这样的效果,那么我们的业务系统的适应能力就得到了极大提升。在这样的背景下,就出现了**工作流引擎**。
**为什么使用工作流引擎,能实现业务流程改变,不用修改代码,流程还能自动推进?**
(1)我们先来说说为什么流程改变,不用修改代码:我们的工作流引擎都实现了一个规范,这个规范要求我们的流程管理与状态字段无关,始终都是读取业务流程图的下一个节点。当业务更新的时候我们只需要更新业务流程图就行了。这就实现了业务流程改变,不用修改代码。
(2)再来说说流程自动推进,这个原理就更简单了,就拿上面的请假模型来说,工作流引擎会用一张表来记录当前处在的节点。当填写完请假单后肯定是要轮到部门经理来审批了,所以我们一旦完成了请假单填写那么这条记录将会被从这张表删除掉,并且会把下一个节点部门经理的信息插入到这张表中,当我们用部门经理的信息去这张表中查询的时候就能查出部门经理相关的审批的信息了,以此类推,这样层层递进,就实现了流程的自动递交了。
1.3、常见工作流引擎
主流的框架有:Activiti、jBPM、Camunda 、Flowable 、还有我们国产的盘古BPM、云程
二、 Activiti7概述
2.1、Activiti介绍
activiti是一个工作流引擎,可以将业务系统中复杂的业务流程抽取出来,使用专门的建模语言BPMN进行定义,业务流程按照预先定义的流程进行执行。实现了系统的流程由activiti进行管理,减少业务系统由于流程变更进行系统升级改造的工作流量,从而提高系统的健壮性,同时也减少了系统开发维护成本。
官方网站:https://www.activiti.org
2.2、建模语言BPMN
BPM(Business Process Management)即业务流程管理,是一种规范化的构造端到端的业务流程,以持续提高组织业务效率
BPM 软件就是根据企业中业务环境的变化,推进人与人之间、人与系统之间以及系统与系统之间的整理及调整的经营方法与解决方案的 IT 工具。使用 BPM 软件对企业内部及外部的业务流程的整个生命周期进行建模、自动化、管理监控和优化,可以降低企业成本,提高利润
BPMN(Business Process Model AndNotation)即业务流程模型和符号,是一套标准的业务流程建模符号,使用 BPMN 提供的符号可以创建业务流程。Activit 就是使用 BPMN 进行流程建模、流程执行管理的
BPMN2.0 是业务流程建模符号 2.0 的缩写,它由 Business Process Management Initiative 这个非营利协会创建并不断发展。BPMN2.0 是使用一些符号来明确业务流程设计流程图的一套符号规范,能增进业务建模时的沟通效率。目前 BPMN2.0 是最新的版本,它用于在 BPM 上下文中进行布局和可视化的沟通
BPMN2.0 的基本符号主要包含:
😊、事件 Event
开始:表示一个流程的开始
中间:发生的开始和结束事件之间,影响处理的流程
结束:表示该过程结束
😊、活动 Activities
活动是工作或任务的一个通用术语。一个活动可以是一个任务,还可以是一个当前流程的子处理流程;其次,你还可以为活动指定不同的类型。常见活动如下:
![67177662480](assets/1671776624801.png)
😊、网关 GateWay
用于表示流程的分支与合并,有几种常用网关需要了解:
- 排他网关:只有一条路径会被选择
- xxxxxxxxxx <el-button type="success" icon="el-icon-plus" size="mini" @click="add" :disabled="$hasBP('bnt.sysRole.add') === false">添 加</el-button>vue
- 包容网关:可以同时执行多条线路,也可以在网关上设置条件
- 事件网关:专门为中间捕获事件设置的,允许设置多个输出流指向多个不同的中间捕获事件。当流程执行到事件网关后,流程处于等待状态,需要等待抛出事件才能将等待状态转换为活动状态
😊、流向 Flow流是连接两个流程节点的连线,常见的流向包含以下几种:
顺序流:用一个带实心箭头的实心线表示,用于指定活动执行的顺序
信息流:用一条带箭头的虚线表示,用于描述两个独立的业务参与者(业务实体/业务角色)之间发送和接受的消息流动
关联:用一根带有线箭头的点线表示,用于将相关的数据、文本和其他人工信息与流对象联系起来。用于展示活动的输入和输出
2.3、 Activiti使用流程
第一步: 引入依赖并初始化数据库
既然activiti是一个框架,那么我们肯定是需要引入对应的jar包坐标的,具体参考代码中的。
第二步: 通过工具绘画流程图
使用 activiti 流程建模工具(activity-designer)定义业务流程(.bpmn 文件)
.bpmn 文件就是业务流程定义文件,通过 xml 定义业务流程。
第三步:流程定义部署;
向 activiti 部署业务流程定义(.bpmn 文件),使用 activiti 提供的 api 向 activiti 中部署.bpmn 文件,
通俗来讲,就是让activiti认识要使用的流程
第四步: 启动一个流程实例(ProcessInstance)
启动一个流程实例表示开始一次业务流程的运行,比如员工请假流程部署完成,如果张三要请假就可以启动一个流程实例,如果李四要请假也启动一个流程实例,两个流程的执行互相不影响,就好比定义一个java类,实例化两个对象一样,部署的流程就好比java类,启动一个流程实例就好比new一个java对象
第五步:用户查询待办任务(Task)
因为现在系统的业务流程已经交给 activiti 管理,通过 activiti 就可以查询当前流程执行到哪了,当前用户需要办理什么任务了,这些 activiti帮我们管理了。实际上我们学习activiti也只是学习它的API怎么使用,因为很多功能activiti都已经封装好了,我们会调用就行了
第六步:用户办理任务
用户查询待办任务后,就可以办理某个任务,如果这个任务办理完成还需要其它用户办理,比如请假单创建后由部门经理审核,这个过程也是由 activiti 帮我们完成了,不需要我们在代码中硬编码指定下一个任务办理人了
第七步:流程结束
当任务办理完成没有下一个任务节点了,这个流程实例就完成了。
三、 Activiti使用
导入pom依赖:
<dependency> <groupId>org.activiti</groupId> <artifactId>activiti-spring-boot-starter</artifactId> <version>7.1.0.M6</version> <exclusions> <exclusion> <artifactId>mybatis</artifactId> <groupId>org.mybatis</groupId> </exclusion> </exclusions> </dependency>
修改yml文件:
activiti: # false:默认,数据库表不变,但是如果版本不对或者缺失表会抛出异常(生产使用) # true:表不存在,自动创建(开发使用) # create_drop: 启动时创建,关闭时删除表(测试使用) # drop_create: 启动时删除表,在创建表 (不需要手动关闭引擎) database-schema-update: true #监测历史表是否存在,activities7默认不开启历史表 db-history-used: true #none:不保存任何历史数据,流程中这是最高效的 #activity:只保存流程实例和流程行为 #audit:除了activity,还保存全部的流程任务以及其属性,audit为history默认值 #full:除了audit、还保存其他全部流程相关的细节数据,包括一些流程参数 history-level: full #校验流程文件,默认校验resources下的process 文件夹的流程文件 check-process-definitions: true
报错异常:
Failed to start bean 'documentationPluginsBootstrapper'; nested exception is java.lang.NullPointerException
解决办法:降低springboot版本
3.1、部署流程工具
第一步:下载并解压
第二步:拷贝到将activiti的wars下的文件tomcat
第三步:启动tomcat服务
第四步:登录并访问:http://localhost:8080/activiti-explorer
登录后页面
3.2、画出流程图并放入项目中
3.3、流程定义部署
@SpringBootTest public class ActivitiTest { @Autowired private RepositoryService repositoryService; //单个文件部署 @Test public void activitiTest1(){ //流程部署 Deployment deployment = repositoryService.createDeployment() .addClasspathResource("process/yyds.bpmn20.xml") .addClasspathResource("process/1.png") .name("请假申请流程") .deploy(); System.out.println(deployment.getId()); System.out.println(deployment.getName()); } }
3.4、启动流程实例
@Autowired
private RuntimeService runtimeService;
//启动流程实例
@Test
public void activitiTest2(){
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("请假");
System.out.println("流程定义ID:" + processInstance.getProcessDefinitionId());
System.out.println("流程实例id:" + processInstance.getId());
System.out.println("当前活动id:" + processInstance.getActivityId());
}
3.5、查询任务
@Autowired
private TaskService taskService;
@Test
public void activitiTest3(){
List<Task> list = taskService.createTaskQuery()
.taskAssignee("高启强")
.list();
for (Task task:list) {
System.out.println("流程实例ID:" + task.getProcessInstanceId());
System.out.println("任务ID:" + task.getId());
System.out.println("任务负责人:" + task.getAssignee());
System.out.println("任务名称:" + task.getName());
}
}
3.6、处理当前任务与处理查询
@Autowired
private HistoryService historyService;
@Test
public void activitiTest4(){
//查询负责人需要处理的任务
Task task = taskService.createTaskQuery()
.taskAssignee("高启强")
.singleResult();
//处理任务
taskService.complete(task.getId());
}
//查询已经处理的任务
@Test
public void activitiTest5(){
List<HistoricTaskInstance> list = historyService.createHistoricTaskInstanceQuery()
.taskAssignee("高启强").list();
for (HistoricTaskInstance historicTaskInstance:list){
System.out.println(historicTaskInstance.getProcessInstanceId());
}
}
3.7、流程实例
//创建流程实例指定key
@Test
public void activitiTest6(){
ProcessInstance instance = runtimeService.startProcessInstanceByKey("请假", "1314");
System.out.println(instance.getBusinessKey());
}
//全部流程实例挂起
@Test
public void activitiTest7(){
//获取流程定义实例
ProcessDefinition singleResult = repositoryService.createProcessDefinitionQuery()
.processDefinitionKey("请假").singleResult();
//调用流程定义对象的方法判断当前状态,挂起、激活
boolean suspended = singleResult.isSuspended();
//如果是挂起就激活,否则就挂起
if (suspended){
//参数1:流程定义id
//参数2:是否激活true
//参数3:时间点
repositoryService.activateProcessDefinitionById(singleResult.getId(),true,null);
log.info(singleResult.getId(),"激活了");
}else {
repositoryService.suspendProcessDefinitionById(singleResult.getId(),true,null);
log.info(singleResult.getId(),"挂起了");
}
}