文章目录
1.Activiti 流程设计器集成与使用
(1)使用 Eclipse 集成 Activiti 流程设计器
下载插件
百度云链接: https://pan.baidu.com/s/1uVbckVTD_puqf0G7x5PXpg 密码:2rbm
解压并放到 Eclipse 目录下
- Eclipse 插件安装方法
Eclipse 插件安装 4 种方法
https://cloud.tencent.com/developer/article/1332826
Eclipse 使用 dropins 的插件安装方式
https://blog.csdn.net/mafly008/article/details/11093549
- 安装 activiti-designer-5.14.1 插件
- 将 activiti-designer-5.14.1 内的两个文件:features 和 plugins 放到 eclipse 的 dropins/activiti-designer-5.14.1 文件内
- 将 eclipse安装activiti需装eclipse插件20170325内的四个文件放到 eclipse 根目录的 plugins 内
创建 Activiti 项目
- File -> New -> Project -> Activiti -> Activiti Project -> Next -> 输入 Project name -> Finish
设计流程
- Project name/src/main/resources/diagrams 包用于存放设计的流程定义 XML 文件
- diagrams下 -> New -> Other -> Activiti Diagram -> Next -> 文件名 -> Finish
以不同格式查看流程内容
- 右击流程文件 -> Open With
打开流程属性页面
- Window -> Show view -> Properties
(2)使用 IDEA 集成 Activiti 流程设计器
- actiBPM 是 IDEA 中的 Activiti 插件,用于提供可视化流程设计能力。
2.流程组件介绍
https://wenku.baidu.com/view/e0f7ce06de36a32d7375a417866fb84ae45cc33e.html
(1)事件
空启动事件
必须⼈⼯去启动⼀个流程。每启动⼀次,产⽣⼀个新的流程实例。只能通过API调⽤startProcessInstanceByXXX⽅法启动⼀个流程实例。⼤多数流程都是以此⽅式开始的,⽅便⽤户⼿动发起流程实例。
定时器启动事件
定时器启动事件⽤于在给定的时间点创建流程实例。可⽤在只启动⼀次的流程中,也可在特定时间间隔下启动。模型⼀旦部署,将会⾃动调度计时器时间,不需要通过API调⽤startProcessInstanceByXXX来启动流程实例,但还是可以通过API调⽤startProcessInstanceByXXX来再次启动。
结束事件
(2)活动列表
用户活动
⽤于对需要由⼈⼯参与者完成的⼯作建模。当流程执⾏到达这样⼀个⽤户任务时,将在分配给该任务的⽤户或组的任务列表中创建⼀个新任务。
代理人 assignee
处理人唯一
<userTask id="usertask1" name="商务采购" activiti:assignee="${assignee}" ></userTask>
候选人 candidateUsers
处理人多个,字符串以" , "分隔
<userTask id="usertask2" name="商务采购" activiti:candidateUsers="${candidateUsers}"> </userTask>
候选组 candidateGroups
在act_id_group中存储的组id
<userTask id="usertask3" name="商务采购" activiti:candidateGroups="${candidateGroups}"> </userTask>
服务任务
⽤于调⽤外部Java类。当下⼀个节点需要⾃动执⾏⼀些操作,并且这个节点不需要任何的⼈⼯⼲涉。操作主要步骤分为:设计流程、编写委托类、把委托类设置到流程的监听类上⾯。
脚本任务
⼀般是⽤在当前的监听器或者监听服务类都不能满⾜的情形下。
邮件任务
Activiti允许通过向⼀个或多个收件⼈发送电⼦邮件的⾃动邮件。
(3)网关
排它网关
只会选择⼀条顺序流。当多条顺序流的条件都计算为true时,其中在XML中定义的第⼀条(也只有这条)会被选择,⽤于继续流程。如果没有可选的顺序流,会抛出异常。
在网关的连线上配置判断条件。
https://blog.csdn.net/wang0907/article/details/120800372
并行网关
⽤于对流程中的并发性进⾏建模。它允许分叉到多个执⾏路径或连接多个传⼊的执⾏路径。
(4)结构列表
子流程
⼦流程完全是在⽗流程中定义 的(这就是为什么它通常被称为嵌⼊式⼦流程)。⼦进程只能有⼀个⽆启动事件,不允许有其他启动事件类型。⼦流程必须⾄少有⼀个end事件。BPMN 2.0规范允许省略⼦流程中的 开始和结束事件,但是当前的Activiti-5.22.0实现不⽀持这⼀点
3.Activiti 数据库设计和模型映射
Activiti 支持多种主流关系型数据库,如 DB2、MySQL、Oracle 等。Activiti 遵循以下命名规则:表名由以下划线连接的部分组成,其中第一部分固定以 ACT 开头,第二部分是表示表用途的两个字母标识,用途与服务的 API 对应,第三部分表示存储的内容。例如,ACT_HI_PROCINST 表示 Activiti 的历史流程实例表。
根据 Activiti 表的命名规则,可以将 Activiti 的数据表划分为以下 5 大类。
- 通用数据表:用于存放流程或业务使用的通用资源数据,这类表以 ACT_GE_ 为前缀,其中 GE 表示 general。
- 流程存储表:用于存放流程定义文件和部署信息等,这类表以 ACT_RE_ 为前缀,其中 RE 表示 repository。
- 身份数据表:用于存放用户、组及关联关系等身份信息,这类表以 ACT_ID_ 为前缀,其中 ID 表示 identity。
- 运行时数据表:用于存放流程执行实例、任务、变量等流程运行过程中产生的数据,这类表以 ACT_RU_ 为前缀,其中 RU 表示 runtime。
- 历史数据表:用于存放历史流程实例、变量和任务等历史记录,这类表以 ACT_HI_ 为前缀,其中 HI表示 history。
3.1 通用数据表
- 通用数据表指 Activiti 中以 ACT_GE_ 开头的表,用于存放流程或业务使用的通用资源数据,主要包括 ACT_GE_BYTEARRAY 资源表和 ACT_GE_PROPERTY 属性表。
- ACT_GE_BYTEARRAY 资源表用于存储与工作流引擎相关的资源数据,Activiti 使用该资源表保存流程定义文件内容、流程图片内容和序列化流程变量等二进制数据。
- ACT_GE_PROPERTY 属性表用于存储整个工作流引擎级别的属性数据,Activiti 将全部属性抽象为 key-value,每个属性都有相应的名称和值。
3.2 流程存储表
- 流程存储表指 Activiti 中以 ACT_RE_ 开头的表,用于存储流程定义和部署信息等,主要包括 ACT_RE_MODEL 表、ACT_RE_DEPLOYMENT 表和 ACT_RE_PROCDEF 表。
- ACT_RE_MODEL 表即流程设计模型表,该数据表主要用于存储流程的设计模型。
- ACT_RE_DEPLOYMENT 表即部署信息表,该表主要用于存储流程定义的部署信息。Activiti 一次部署可以添加多个资源,资源保存在 ACT_GE_BYTEARRAY 资源表中,部署信息则保存在该表中。
- ID_ 部署记录ID
- CATEGORY_ 分类:在部署时定时,可用来对流程分类
- ACT_RE_PROCDEF 表即流程定义数据表,该表主要用于存储流程定义信息。Activiti 部署流程时,除了将流程定义文件存储到资源表之外,还会解析流程定义文件内容,生成流程定义保存在该表中。
- ID_ 流程定义ID
3.3 身份数据表
- 身份数据表指 Activiti 中以 ACT_ID_ 开头的表,用于存储用户、组、关系等身份信息,主要包括 ACT_ID_USER 表、ACT_ID_INFO 表、ACT_ID_GROUP 表和 ACT_ID_MEMBERSHIP 表。
- ACT_ID_USER 表即用户表,该表主要用于存储用户基本信息数据,不是必须的。
- ID_ 用户ID
- ACT_ID_INFO 表即用户账号信息表,该表主要用于存储用户账号、用户信息等。Activiti 将信息分为用户、用户账号和用户信息 3 种信息类型。其中,用户保存在 ACT_ID_USER 表中,用户账号和用户信息保存在该表中。
- ID_ 账号ID
- USER_ID 用户ID
- PASSWORD 密码
- ACT_ID_GROUP表即用户组表,该表主要用于存储用户组数据。
- ID_ 用户组ID
- NAME_ 用户组类型
- ACT_ID_MEMBERSHIP 表即用户与用户组关系表,该表主要用于存储用户与用户组的关系,一个用户组可以有多个用户,一个用户也可以隶属于多个用户组。
- ACT_ID_USER 表即用户表,该表主要用于存储用户基本信息数据,不是必须的。
4.流程操作
RepositoryService
RepositoryService是Activiti的仓库服务类。所谓的仓库指流程定义文档的两个文件:bpmn文件和流程图片
(1)流程部署
主要对应操作表:
- act_re_deployment(部署对象表):存放流程定义的名称和部署时间,每部署一次增加一条记录。
- act_re_procdef(流程定义表):存放流程定义的属性信息,部署每个新的流程定义都会在这张表中增加一条记录。当流程定义的key相同的情况下,使用的是版本升级。
- act_ge_bytearray(资源文件表):存储流程定义相关的部署信息。即流程定义文档的存放地。每部署一次就会增加两条记录,一条是关于bpmn规则文件的,一条是图片的,都是以二进制形式存储在数据库中。
@Configuration
public class BPMNResourceConfig {
@Autowired private
RepositoryService repositoryService;
@Bean("testDeployment")
public Deployment testDeployment() {
// DeploymentBuider属于部署层
DeploymentBuider deploymentBuilder = repositoryService.createDeployment()
Deployment deployment = deploymentBuilder.key("test").name("测试流程").addClasspathResource("process/testProcess.bpmn").deploy()
log.info(deployment.getKey()); // 部署英文名:test
log.info(deployment.getId()); // 系统生成的部署Id
log.info(deployment.getKey()); // test
return deployment;
}
}
(2)流程定义
在启动实例时会用到流程的KEY。
@Configuration
public class BPMNTemplateConfig {
@Autowired
private RepositoryService repositoryService;
@Resource(name = "testDeployment")
private Deployment testDeployment;
@Bean("testProcessDefinition")
public ProcessDefinition testProcessDefinition() {
ProcessDefinitionQuery query = repositoryService.createProcessDefinitionQuery();
ProcessDefinition processDefinition = query.deploymentId(testDeployment.get Id()).singleResult()
log.info(processDefinition.getKey()); // bpmn中Process的Id, 流程英文名, 如 operationIndex
log.info(processDefinition.getId()); // operationIndex:2:38833-11vsf-1121f-12efac-12e1113
log.info(processDefinition.getName()); // bpmn中Process的Name, 流程中文名
log.info(processDefinition.getDeploymentId()); // 流程部署Id
log.info(processDefinition.getResourceName()); // 资源名称, 如 process/operationIndex.bpmn
return processDefinition;
}
}
(3)查询流程部署
public void testDeploymentQuery(){
List<Deployment> myEvection = repositoryService.createDeploymentQuery()
.processDefinitionKey(testProcessDefinition.getKey()) // 流程定义的Key
.orderByDeploymenTime().desc()
.list();
for (Deployment deployment : myEvection) {
System.out.println(deployment);
}
}
(4)删除流程部署
public void testDeploymentQuery(){
List<Deployment> myEvection = repositoryService.createDeploymentQuery()
.processDefinitionKey(testProcessDefinition.getKey()) // 流程定义的Key
.orderByDeploymenTime().desc()
.list().get(0);
if(myEvection != null){
// 普通删除, 如果当前规则下有正在执行的流程, 则抛出异常
// repositoryService.deleteDeployment(deployment.getId());
// 级联删除, 会删除和当前规则相关的所有信息, 正在执行的信息, 也包括历史信息
repositoryService.deleteDeployment(myEvection.getId(), true);
}
}
(5)流程定义挂起
某些情况可能由于流程变更需要将当前运行的流程暂停而不是直接删除,流程暂停后将不会继续执行。
repositoryService.suspendProcessDefinitionById(processDefinitionId,true,null);
(6)流程定义激活
repositoryService.activateProcessDefinitionById(processDefinitionId,true,null);
(7)获取bpmn详情(☆☆☆)
// 所有bpmn节点的信息
BpmnModel bpmnModel = repositoryService.getBpmnModel(historyTaskInfo.getProcessDefinitionId());
Collection<FlowElement> flowElements = bpmnModel.getMainProcess().getFlowElements();
Iterator<FlowElement> iterator = flowElements.iterator();
while (iterator.hasNext()) {
FlowElement next = iterator.next();
System.out.println(next.getId() + "-" + next.getName()); // startevent1-流程开启
}
// 指定bpmn中节点的信息
UserTask> userTask = (UserTask)bpmnModel.getMainProcess().getFlowElements(historyTaskInfo.getProcessDefinitionId());
log.info(userTask.getCandidateUsers(), userTask.getCandidateGroups());
RuntimeService
是activiti的流程执行服务类。可以从这个服务类中获取很多关于流程执行相关的信息。
(1)开启流程
主要对应操作表:
- act_ru_execution:如果是用户任务节点,同时也会在act_ru_task添加一条记录。
- act_ru_identitylink:任务参与者数据表。主要存储当前节点参与者的信息。
public String startInstance(){
Map<String,Object> varMap = new HashMap<>();
varMap.put("apply","A6582"); // user
varMap.put("checkGroup", "2001"); // group
ProcessInstance processInstance = runtimeService.startProcessInstanceById(testProcessDefinition.getId(), varMap);
return processInstance.getId();
}
(2)挂起流程实例
runtimeService.suspendProcessInstanceById(processInstanceId);
(3)激活流程实例
runtimeService.activateProcessInstanceById(processInstanceId);
(4)删除流程
runtimeService.deleteProcessInstance(processInstanceId, "删除测试");
(5)流程参数设置
https://blog.csdn.net/ITWANGBOIT/article/details/106507332
runtimeService.getVariable(processInstance.getId(), "apply"); // A6582
runtimeService.setVariable(processInstance.getId(), "apply", "A6582");
runtimeService.setVariableLocal(processInstance.getId(), "apply", "A6582"); // 只有当前子流程能拿到
TaskService
是activiti的任务服务类。可以从这个类中获取任务的信息。
(1)查询task(未处理任务☆☆☆)
Task task = taskService.createTaskQuery()
.processInstanceId(processInstance.getId())
.taskCandidaterOrAssigned("A6582")
.singleResult();
(2)任务参数设置
https://blog.csdn.net/ITWANGBOIT/article/details/106544672
taskService.getVariable(task.getId(), "apply");
taskService.setVariable(task.getId(), "apply", "A6582");
taskService.setVariableLocal(task.getId(), "apply", "A6582"); // 只有当前任务能拿到
(3)完成任务
act_ru_task:对于执行完的任务,activiti将从act_ru_task表中删除该任务,下一个任务会被插入进来。
public void complete( @RequestParam(name = "userId") String userId, @RequestParam(name = "instanceId") String instanceId){
Task task = taskService.createTaskQuery().processInstanceId(instanceId).taskCandidateOrAssig ned(userId).singleResult();
taskService.complete(task.getId());
taskService.addComment(task.getId(), instanceId, comment);
List<Comment> com = taskService.getTaskComment(task.getId());
}
HistoryService
https://www.jianshu.com/p/9b1ea194da13
是activiti的查询历史信息的类。在一个流程执行完成后,这个对象为我们提供查询历史信息。
createHistoricProcessInstanceQuery 当前、已结束的流程实例信息
historyService.createHistoricProcessInstanceQuery()
.finished()
.processDefinitionId("XXX")
.list();
createHistoricActivityInstanceQuery 流程节点执行信息
historyService.createHistoricActivityInstanceQuery()
.finished()
.processInstanceId("XXX")
.list();
createHistoricVariableInstanceQuery 流程或任务变量
historyService.createHistoricVariableInstanceQuery()
.processInstanceId("XXX")
.list();
createHistoricTaskInstanceQuery 当前、已完成、已删除任务实例信息(历史节点☆☆☆)
list<HistoricTaskInstance> list = historyService.createHistoricTaskInstanceQuery()
.processInstanceId("XXX").list();
list.forEach(historyTaskInfo -> {
log.info(historyTaskInfo.getName()); // 节点名称
log.info(historyTaskInfo.getId()); // 任务Id
log.info(historyTaskInfo.getStartTime()); // 开始时间
log.info(historyTaskInfo.getEndTime()); // 结束时间
log.info(historyTaskInfo.getDeleteReason()); // 删除原因
log.info("处理人");
log.info("部门");
})
5.监听器
https://blog.csdn.net/sadoshi/article/details/104698749/
任务监听器
顾名思义是监听任务的。任务监听器的生命周期如下图所示,会经历assignment、create、
complete、delete。当流程引擎触发这四种事件类型时,对应的任务监听器会捕获其事件类型,再按照
监听器的处理逻辑进行处理。
public class MyTaskListener implements TaskListener{
public void notify(DelegateTask delegateTask) {
String eventName = delegateTask.getEventName();
if ("create".endswith(eventName)) {
}
if ("complete".endswith(eventName)) {
}
}
执行监听器
监听流程的所有节点和连线。主要有start、end、take事件。其中节点有start、end两种
事件,而连线则有take事件。
public class MyExecutionListener implements ExecutionListener {
public void notify(DelegateExecution execution) throws Exception {
String eventName = execution.getEventName();
if ("start".endswith(eventName)) {
}
if ("end".endswith(eventName)) {
}
}
下图是执行监听器的生命周期:
在插件中Listeners指定监听器的代码位置(org.activiti.engine.delegate.DelegateExecution)。