一、Activiti7介绍
一个示例教你快速掌握activiti流程引擎
Activiti是目前使用最为广泛的开源工作流引擎,2010年5月就正是启动了。在了
解Activiti之前,我们首先要了解下什么是工作流。
1.1 工作流WorkFlow
- 关于什么是工作流,有一个官方的定义: 工作流是指一类能够完全自动执行的经营过程,根据一系列规程规则,将文档、信息或任务在不同的执行者之间进行传递和执行。其实说直白一点,就是业务上一个完整的审批流程。例如员工的入职、请假、出差、采购等等、还有一些关键业务如订单申请、合同审核等等,这些过程,都是一个工作流。
- 对于工作流,传统的处理方式往往需要有人拿着各类的文件,在多个执行部门之间不断的审批。而当我们开始用软件来协助处理这一类审批流程时,就开始出现了工作流系统。工作流系统可以减少大量的线下沟通成本,提高工作效率。
- 有了工作流系统之后,才开始出现工作流引擎。在没有专门的工作流引擎之前,我们为了实现这样的流程控制,通常的做法都是采用状态字段的方式来跟踪流程的变化情况。例如对一个员工请假请求,我们会定义已申请、组长已审核、部门经理已审核等等这样一些状态,然后通过这些状态来控制不同的业务行为,比如部门经理角色只能看到组长已审核通过的,并且请假天数超过3天的订单等等。
- 这种实现方式实现起来比较简单,也是软件系统中非常常用的一种方式。但是这种通过状态字段来进行流程控制的方式还是有他的弊端。
- 一方面:整个流程定义不够清晰。业务流程是分散在各个业务阶段中的,从代码的角度非常难以看到整个流程是如何定义的。
- 另一方面:当流程发生变更时,这种方式编写的代码就需要做非常大的变更。例如从三级审批要增加为四级审批甚至是协同审批,那各个业务阶段的审批流程都需要随之做大量的变更。
- 正是出于这些痛点,后面才有了工作流引擎。使用工作流引擎后,整个审批流程可以在同一个地方进行整体设计,并且当审批流程发生变更时,业务程序也可以不用改变。这样业务系统的适应能力就得到了极大提升。
其实引擎的思想无处不在。我们有Drools规则引擎,可以在程序不发生
变动的情况下,集中定义业务规则并进行修改。Aviator表达式引擎,可
以快速计算某一个表达式的结果。搜索引擎,可以快速进行统一搜索等
等。其核心思想都是将业务之间的共性抽取出来,减少业务变动对程序
的影响。
1.2 Activiti工作流引擎
Activiti正是目前使用最为广泛的开源工作流引擎。Activiti的官网地址是 https://www.activiti.org 历经6.x和5.x两个大的版本,目前最新的版本是 Activiti Cloud7.1.0-M11。
他可以将业务系统中复杂的业务流程抽取出来,使用专门的建模语言BPMN2.0进行定义。业务流程按照预先定义的流程执行,整个实现流程完全由activiti进行管理,从而减少业务系统由于流程变更进行系统改造的工作量,从而减少系统开发维护成本,提高系统的健壮性。所以使用Activiti,重点就是两个步骤,首先使用BPMN定义流程,然后使用Activiti框架实现流程。
1.3 建模语言BPMN
- 谈到BPMN,首先就要谈BPM。 BPM即Business Process Managemenet,业
务流程管理。是一种规范化的构造端到端的业务流程,以持续的提高组织业务效
率。在常见的商业管理教育如EMBA、MBA中都包含了BPM的课程。 - 有了BPM的需求,就出现了BPM软件。他是根据企业中业务环境的变化,推进人
与人之间,人与系统之间以及系统与系统之间的整合及调整的经营方法域解决方案
的IT工具。通过对企业业务流程的整个生命周期进行建模、自动化、管理监控和优
化,使企业成本降低,利润得到提升。BPM软件在企业中应用非常广泛,凡是有业
务流程的地方都可以使用BPM进行管理。比如企业人事办公管理、采购流程管理、
公文审批流程管理、财务管理等。 - 而BPMN是Business Process Model And Notation 业务流程模型和符号,就是
用来描述业务流程的一种建模标准。BPMN最早由BPMI(BusinessProcessManagement Initiative)方案提出。由一整套标准的业务流程建模符号组成。使用BPMN可以快速定义业务流程。
BPMN最早在2004年5月发布。2005年9月开始并入OMG(The Object Managemenet Group)组织。OMG于2011年1月发布BPMN2.0的最终版本。 - BPMN是目前被各大BPM厂商广泛接受的BPM标准。Activiti就是使用BPMN2.0进
行流程建模、流程执行管理。整个BPMN是用一组符号来描述业务流程中发生的各种事件的。BPMN通过在这些符号事件之间连线来描述一个完整的业务流程。
而对于一个完整的BPMN图形流程,其实最终是通过XML进行描述的。通常,会
将BPMN流程最终保存为一个.bpmn的文件,然后可以使用文本编辑器打开进行查
看。而图形与xml文件之间,会有专门的软件来进行转换。
关于如何配置一个工作流,在后面的实战过程中我们会接触到。
1.4 Activiti使用步骤
通常使用Activiti时包含以下几个步骤:
- 部署activiti: Activiti包含一堆Jar包,因此需要把业务系统和Activiti的环境集成
在一起进行部署。 - 定义流程: 使用Activiti的建模工具定义业务流程.bpmn文件。
- 部署流程定义: 使用Activiti提供的API把流程定义内容存储起来,在Acitivti执行
过程汇总可以查询定义的内容。Activiti是通过数据库来存储业务流程的。 - 启动流程实例: 流程实例也叫ProcessInstance。启动一个流程实例表示开始一
次业务流程的运作。例如员工提交请假申请后,就可以开启一个流程实例,从而
推动后续的审批等操作。 - 用户查询待办任务(task):因为现在系统的业务流程都交给了activiti管理,通过
activiti就可以查询当前流程执行到哪个步骤了。当前用户需要办理哪些任务也就
同样可以由activiti帮我们管理,开发人员不需要自己编写sql语句进行查询了。 - 用户办理任务:用户查询到自己的待办任务后,就可以办理某个业务,如果这个
业务办理完成还需要其他用户办理,就可以由activiti帮我们把工作流程往后面的
步骤推动。 - 流程结束:当任务办理完成没有下一个任务节点后,这个流程实例就执行完成
了。
了解这些后,我们来开始进入实战内容。
二、Activiti环境搭建
使用Activiti需要的基本环境包括: JDK 8或以上版本;然后需要一个数据库用来保
存流程定义数据,建议mysql 5或以上版本。
2.1 安装插件
开发工具IDEA,在IDEA中需要安装Activiti的流程定义工具插件actiBPM。目前该插
件从2014年11月后就没有再更新,对于IDEA版本只支持到2019.1。新版本的IDEA
已经无法从插件市场搜索到该插件。安装时,可以到jetBrain的插件市场 https://pl
ugins.jetbrains.com/ 搜索actiBPM插件,下载到本地后,从本地安装该插件。
三、使用idea创建、部署、并运行流程
3.1 创建流程
在新建文件时,选择我们上述已经安装的插件类型来新建文件。
新建完成后使用安装插件类型的方式来打开文件
打开后我们便可以看到一个面板,即可在该面板下创建新流程
流程的创建:需要遵循active流程引擎的规范,具体的一些规范介绍与流程字段说明,这里我就不一一介绍了,以下推荐一篇博客可参考学习
active流程引擎整合idea从0到1
3.2 流程部署
流程部署使用了 (流程引擎)ProcessEngine 来就行部署,这里展示一个简单的流程部署demo
//启动流程4,通过接口直接启动流程
@GetMapping("/arrangeStart4")
@ApiOperation("部署流程4")
public String arrangeStart4(){
//1、创建ProcessEngine
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//2、得到RepositoryService实例
RepositoryService repositoryService = processEngine.getRepositoryService();
//3、使用RepositoryService进行部署
Deployment deployment = repositoryService.createDeployment()
.addClasspathResource("processes/flowFour.bpmn20.xml") // 添加bpmn资源
//png资源命名是有规范的。Leave.myLeave.png|jpg|gif|svg 或者Leave.png|jpg|gif|svg
.addClasspathResource("processImg/flowFour.png") // 添加png资源
.name("测试流程4")
.deploy();
//4、输出部署信息
System.out.println("流程部署id:" + deployment.getId());
System.out.println("流程部署名称:" + deployment.getName());
return "ok";
}
==部署方式比较简单,这里为了方便部署 我将部署封装成接口的方式,来就行部署,部署只需要将 添加的bpmn资源路径改成你所创建的流程路径即可 ==
这里展示一下我的文件路径设置
接口封装完后,只需要调用该方法即可完成该流程的部署
3.3 流程运行
本文只展示简单流程的运行demo
package com.park.activiti.controller;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.park.activiti.domain.dto.AlarmModuleFlowParam;
import com.park.activiti.domain.dto.FlowFourKPOV;
import com.park.activiti.domain.dto.FlowOneKPOV;
import com.park.activiti.domain.dto.FlowTwoKPOV;
import com.park.activiti.domain.util.SecurityUtil;
import com.park.activiti.service.*;
import com.park.common.constant.FlowConstants;
import com.park.common.constant.FlowFourConstants;
import com.park.common.constant.FlowOneConstants;
import com.park.common.core.domain.AjaxResult;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.activiti.engine.*;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Slf4j
@Validated
@Api(value = "测试activiti流程引擎接口", tags = {
"测试activiti接口" })
@RequiredArgsConstructor
@RestController
@RequestMapping("/actuator/testStartInstance")
public class TestController {
@Autowired
private AlarmModuleStartFlowService alarmModuleStartFlowService;
/** * 流程4:启动测试接口 * @return */
@RequestMapping("/startAlarmFlowFour")
@ResponseBody
public AjaxResult startAlarmFlowFour(){
AlarmModuleFlowParam alarmModuleFlowParam = new AlarmModuleFlowParam();
alarmModuleFlowParam.setAlarmContent("测试报警内容4");
alarmModuleFlowParam.setDeviceId(2L);
alarmModuleFlowParam.setDeviceName("杭州-测试");
alarmModuleFlowParam.setSerialNumber("H6测试");
alarmModuleFlowParam.setDeviceType(3L);
alarmModuleFlowParam.setDevicePlace("流程预警测试");
alarmModuleFlowParam.setSensor("PH");
alarmModuleFlowParam.setAlarmData("12.41");
alarmModuleFlowParam.setReportTime(new Date());
alarmModuleFlowParam.setPointSerialNumber("H6测试");
alarmModuleFlowParam.setPointName("杭州-测试");
alarmModuleFlowParam.setPointPlace("测试位置4");
alarmModuleFlowParam.setPointMark("其他");
alarmModuleFlowParam.setPointType(0);
alarmModuleFlowParam.setFlowId(FlowConstants.FLOW_Four_ID);
alarmModuleStartFlowService.startFlow(alarmModuleFlowParam);
return AjaxResult.success();
}
//启动流程4,通过接口直接启动流程
@GetMapping("/arrangeStart4")
@ApiOperation("部署流程4")
public String arrangeStart4(){
//1、创建ProcessEngine
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//2、得到RepositoryService实例
RepositoryService repositoryService = processEngine.getRepositoryService();
//3、使用RepositoryService进行部署
Deployment deployment = repositoryService.createDeployment()
.addClasspathResource("processes/flowFour.bpmn20.xml") // 添加bpmn资源
//png资源命名是有规范的。Leave.myLeave.png|jpg|gif|svg 或者Leave.png|jpg|gif|svg
.addClasspathResource("processImg/flowFour.png") // 添加png资源
.name("测试流程4")
.deploy();
//4、输出部署信息
System.out.println("流程部署id:" + deployment.getId());
System.out.println("流程部署名称:" + deployment.getName());
return "ok";
}
//启动流程4,通过接口直接启动流程
@GetMapping("/start4")
@ApiOperation("启动流程4")
public String testStart4Instance(){
// 定义流程变量
Map<String, Object> variables = new HashMap<String, Object>();
FlowFourKPOV flowFourKPOV = new FlowFourKPOV();
flowFourKPOV.setGwhStaff("gwh_staff_1");
flowFourKPOV.setGwhManager("gwh_manager_1");
flowFourKPOV.setTester("tester");
flowFourKPOV.setIsPass(true);
variables.put(FlowFourConstants.GLOBAL_PROCESS_VARIABLE,flowFourKPOV);
//启动流程4
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(FlowConstants.FLOW_Four_ID,variables);
//查看流程获取情况
System.out .println("流程定义id:" +processInstance.getProcessDefinitionId());
System.out.println("流程实例id:" + processInstance.getId());
System.out.println("当前活动Id:" + processInstance.getActivityId());
return "ok";
}
/** * 园区管委会安排处置员工-处理该节点审核 */
@ApiOperation("执行流程4:节点1")
@GetMapping("/processTask1")
public AjaxResult processTask1(){
//任务4:节点1负责人
String assignee = "gwh_staff_1";
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//创建TaskService
TaskService taskService = processEngine.getTaskService();
//根据流程key 和 任务负责人 查询任务
Task task = taskService
.createTaskQuery()
.processDefinitionKey(FlowConstants.FLOW_Four_ID)
.taskAssignee(assignee)
.singleResult();
//该流程节点负责人 完成该节点任务,参数:任务id
taskService.complete(task.getId());
JSONObject jsonObject = JSONUtil.parseObj(task);
AjaxResult<Object> ajaxResult = new AjaxResult<>();
ajaxResult.setData(jsonObject);
return ajaxResult;
}
/** * 园区管委会安排处置管理员-处理节点 */
@ApiOperation("执行流程4:节点2")
@GetMapping("/processTask2")
public AjaxResult processTask2(){
//任务4:节点2负责人
String assignee = "gwh_manager_1";
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//创建TaskService
TaskService taskService = processEngine.getTaskService();
//创建repositoryService
RepositoryService repositoryService = processEngine.getRepositoryService();
//根据流程key 和 任务负责人 查询任务
Task task = taskService
.createTaskQuery()
.processDefinitionKey(FlowConstants.FLOW_Four_ID)
.taskAssignee(assignee)
.singleResult();
// List<Task> list = taskService
// .createTaskQuery()
// .processDefinitionKey(FlowConstants.FLOW_Four_ID)
// .taskAssignee(assignee)
// .list();
// for (Task task:
// list) {
// System.out.println(task.getId());
// System.out.println(task.getProcessDefinitionId());
// //runtimeService.deleteProcessInstance(task.getProcessInstanceId(),"test");
// //repositoryService.deleteDeployment(task.getProcessInstanceId(),true);
// }
//该流程节点负责人 完成该节点任务,参数:任务id
taskService.complete(task.getId());
JSONObject jsonObject = JSONUtil.parseObj(task);
AjaxResult<Object> ajaxResult = new AjaxResult<>();
ajaxResult.setData(jsonObject);
return ajaxResult;
}
/** * 测试人员:王海林1 审核-处理节点 */
@ApiOperation("执行流程4:节点3-1")
@GetMapping("/processTaskTest3")
public AjaxResult processTaskTest3(){
//任务4:节点2负责人
String assignee = "tester";
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//创建TaskService
TaskService taskService = processEngine.getTaskService();
//根据流程key 和 任务负责人 查询任务
Task task = taskService
.createTaskQuery()
.processDefinitionKey(FlowConstants.FLOW_Four_ID)
.taskAssignee(assignee)
.singleResult();
//该流程节点负责人 完成该节点任务,参数:任务id
taskService.complete(task.getId());
JSONObject jsonObject = JSONUtil.parseObj(task);
AjaxResult<Object> ajaxResult = new AjaxResult<>();
ajaxResult.setData(jsonObject);
return ajaxResult;
}
/** * 测试人员:王海林1 审核-处理节点 */
@ApiOperation("执行流程4:节点3-2")
@GetMapping("/processTaskTest4")
public AjaxResult processTaskTest4(){
//任务4:节点2负责人
String assignee = "tester";
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//创建TaskService
TaskService taskService = processEngine.getTaskService();
//根据流程key 和 任务负责人 查询任务
Task task = taskService
.createTaskQuery()
.processDefinitionKey(FlowConstants.FLOW_Four_ID)
.taskAssignee(assignee)
.singleResult();
//该流程节点负责人 完成该节点任务,参数:任务id
taskService.complete(task.getId());
JSONObject jsonObject = JSONUtil.parseObj(task);
AjaxResult<Object> ajaxResult = new AjaxResult<>();
ajaxResult.setData(jsonObject);
return ajaxResult;
}
/** * 删除流程实例 */
@ApiOperation("删除流程实例")
@GetMapping("/deleteTaskTest4")
public AjaxResult deleteTaskTest4(){
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//创建 repositoryService
RepositoryService repositoryService = processEngine.getRepositoryService();
Long count1 = runtimeService.createProcessInstanceQuery().count();
log.info("删除前流程实例数量:" + count1);
//获取部署
ProcessDefinition processDefinition= repositoryService.createProcessDefinitionQuery()
.processDefinitionKey(FlowConstants.FLOW_Four_ID)
.singleResult();
//根据部署id删除已部署的流程
repositoryService.deleteDeployment(processDefinition.getDeploymentId(), true);
Long count2 = runtimeService.createProcessInstanceQuery().count();
log.info("删除后流程实例数量:" + count2);
Map<String, Long> map = new HashMap<>();
map.put("before",count1);
map.put("after",count2);
return AjaxResult.success(map);
}
/** * 查询流程实例 */
@ApiOperation("查询流程实例")
@GetMapping("/viewTaskTest4")
public AjaxResult viewTaskTest4(){
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
// 获取RunTimeService
RuntimeService runtimeService = processEngine.getRuntimeService();
List<ProcessInstance> list = runtimeService
.createProcessInstanceQuery()
.processDefinitionKey(FlowConstants.FLOW_Four_ID)
.list();
for (ProcessInstance processInstance : list) {
System.out.println("----------------------------");
System.out.println("流程实例id:"
+ processInstance.getProcessInstanceId());
System.out.println("所属流程定义id:"
+ processInstance.getProcessDefinitionId());
System.out.println("是否执行完成:" + processInstance.isEnded());
System.out.println("是否暂停:" + processInstance.isSuspended());
System.out.println("当前活动标识:" + processInstance.getActivityId());
System.out.println("业务关键字:"+processInstance.getBusinessKey());
}
return AjaxResult.success(list);
}
@Autowired
private RuntimeService runtimeService;
@Autowired
private TaskExecuteService taskExecuteService;
@Autowired
private TaskService taskService;
//启动实例测试
@RequestMapping("/start")
public String testStartInstance(){
// 定义流程变量
Map<String, Object> variables = new HashMap<String, Object>();
FlowOneKPOV flowOneKPOV = new FlowOneKPOV();
flowOneKPOV.setParkUsers("admin,ry");
variables.put(FlowOneConstants.GLOBAL_PROCESS_VARIABLE,flowOneKPOV);
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(FlowConstants.FLOW_ONE_ID,variables);
System.out .println("流程定义id:" +processInstance.getProcessDefinitionId());
System.out.println("流程实例id:" + processInstance.getId());
System.out.println("当前活动Id:" + processInstance.getActivityId());
System.out.println("当前流程节点名称:" + processInstance.getName());
return "ok";
}
@Autowired
private SecurityUtil securityUtil;
}
今天的文章activiti6.0工作流引擎深度解析_工作流引擎开源分享到此就结束了,感谢您的阅读。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/81846.html