Activiti工作流(二)之常用操作

时间:2022-12-24 22:43:27

前面介绍了Activiti工作流的基本操作,但是在实际应用过程中,往往不满足项目需求,因此还需要了解一些其他的功能比如:连线、排他网关、并行网管、流程变量、个人任务及组任务的三种发布方式。

下面将介绍Activiti工作流中的连线操作

首先需要构建一个流程实例并且部署到项目中去

Activiti工作流(二)之常用操作
 可以看出这个流程实例和之前的有一些区别,就是连线上多了一下文字,要想让流程引擎通过连线来辨别走哪个流程需要在连线上加上对应的条件,比如${message=="不紧急"},然后再在完成任务的时候讲该信息封装到map中并传递给流程引擎

  @Test
public void compileTask(){
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine(); //任务ID
String taskID = "302"; //获得任务服务
TaskService taskService = processEngine.getTaskService(); Map<String, Object> map = new HashMap<String, Object>();
map.put("message", "不紧急"); taskService.complete(taskID, map);
}

这样流程引擎就会将该任务分配给部门主管,通过对连线的设置可以手动的将任务分配给指定的人,但是在实际应用过程中,往往还需要一个默认执行的流程,这时候就需要排他网关

首先构建一个新的流程实例并且部署上去

Activiti工作流(二)之常用操作
 在排他网关中,我们需要设置一个Default flow,里面填上需要默认执行连线的ID,且其它连线需要设置对应的Condition,在流程任务执行任务的过程中,当检测到没有一条连线符合我们需要执行的流程的条件时,排他网关会默认的将该任务分配给默认的连线,这里有几点需要注意:

1) 决策网关只会返回一条结果。当流程执行到排他网关时,流程引擎会自动检索网关出口,从上到下检索如果发现第一条决策结果为true或者没有设置条件的(默认为成立),则流出。

2) 如果没有任何一个出口符合条件,则抛出异常

3) 使用流程变量,设置连线的条件,并按照连线的条件执行工作流,如果没有条件符合的条件,则以默认的连线离开

接下来是并行网关,首先创建流程实例并且部署到项目上

Activiti工作流(二)之常用操作
 当该流程启动之后,观察数据库中的表的数据

首先观察ACT_RU_TASK表,这里面是我们需要执行的task

Activiti工作流(二)之常用操作
 然后再看ACT_RU_EXECUTION表,这张表很重要,体现了并行网关的功能

Activiti工作流(二)之常用操作
 接下来我们先完成付款和收款任务,然后再观察这两张表里面的数据

Activiti工作流(二)之常用操作
 
Activiti工作流(二)之常用操作
 可以看见在ACT_RU_TASK表中已经少了一项数据,但是在ACT_RU_EXECUTION表中数据还没有变,接下来再去完成发货和收获任务,然后再观察着两张表

Activiti工作流(二)之常用操作
 
Activiti工作流(二)之常用操作
 可以看见这两张表中都已经没有了任何数据,尤其是ACT_RU_EXECUTION表,这张表只有当并行网关中的所有任务都执行完毕之后数据才会消失。

并行网关不会解析条件。 即使顺序流中定义了条件,也会被忽略,同时并行网关是不需要平衡的。

然后再看流程变量,流程变量相对简单,只需要写两个方法,一个方法设置流程变量,一个方法获取流程变量即可,只需要注意一点,流程变量可以设置和获取一个实体类对象,这里直接贴出代码

@Test
public void setVariables(){
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine(); String assigneeUser = "Asen";
String instanceId = "101"; TaskService taskService = processEngine.getTaskService(); Task task = taskService.createTaskQuery()
.taskAssignee(assigneeUser)
.processInstanceId(instanceId)
.singleResult(); Person person = new Person("Meixi", 30, "Asen3245243", "13090908080"); taskService.setVariable(task.getId(), "取钱人", "Ronaldo");
taskService.setVariableLocal(task.getId(), "金额", "10000");
taskService.setVariable(task.getId(), "取钱人信息", person); } @Test
public void getVariables(){
String assignUser = "Asen";
String instanceId = "101"; ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine(); TaskService taskService = processEngine.getTaskService(); Task task = taskService.createTaskQuery()
.taskAssignee(assignUser)
.processInstanceId(instanceId)
.singleResult(); String user = (String) taskService.getVariable(task.getId(), "取钱人");
String money = (String) taskService.getVariable(task.getId(), "金额");
Person personMessage = (Person) taskService.getVariable(task.getId(), "取钱人信息"); System.out.println("user:" + user + " money:" + money + " personMessage:" + personMessage);
}

最后就是个人任务及组任务的三种分配方式,其中个人任务和组任务的分配方式大同小异,首先是个人任务的分配,第一种就是直接Assign给一个人名(字符串)

Activiti工作流(二)之常用操作
 第二种就是封装成一个map传递给流程引擎

Activiti工作流(二)之常用操作

ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
@Test
public void testTask() throws Exception { InputStream inputStreamBpmn = this.getClass().getResourceAsStream("taskProcess.bpmn");
InputStream inputStreamPng = this.getClass().getResourceAsStream("taskProcess.png");
processEngine.getRepositoryService()//
.createDeployment()//
.addInputStream("userTask.bpmn", inputStreamBpmn)//
.addInputStream("userTask.png", inputStreamPng)//
.deploy(); Map<String, Object> variables = new HashMap<String, Object>();
variables.put("userID", "Ronaldo");
ProcessInstance pi = processEngine.getRuntimeService()
.startProcessInstanceByKey("taskProcess",variables);
}

第三种分配方式使用类,这时候不需要指定办理人,直接添加一个类即可

Activiti工作流(二)之常用操作
 
Activiti工作流(二)之常用操作
 
Activiti工作流(二)之常用操作
 此时的bpmn_xml文件内容已经发生变化

<userTask id="usertask1" name="付款" activiti:assignee="Asen">
<extensionElements>
<activiti:taskListener event="create" class="com.asen.entity.Person"></activiti:taskListener>
</extensionElements>
</userTask>

最后我们需要手动添加一个类去实现TaskListener接口,并且重写notify方法,在该方法中我们需要去指定个人任务

@Override
public void notify(DelegateTask delegateTask) {
String assignee = "Ronaldo";
//指定个人任务
delegateTask.setAssignee(assignee);
}

然后就可以去查询了

@Test
public void findMyTaskList(){
String userId = "Ronaldo";
List<Task> list = processEngine.getTaskService()//
.createTaskQuery()//
.taskAssignee(userId)//指定个人任务查询
.list();
for(Task task:list ){
System.out.println("id="+task.getId());
System.out.println("name="+task.getName());
System.out.println("assinee="+task.getAssignee());
System.out.println("createTime="+task.getCreateTime());
System.out.println("executionId="+task.getExecutionId()); }
}

组任务的三种分配方式就太过详细的写出来了

分配方式一:

Activiti工作流(二)之常用操作
 分配方式二:

Activiti工作流(二)之常用操作

//部署流程定义,启动流程实例
@Test
public void testTask() throws Exception {
// 1 发布流程
InputStream inputStreamBpmn = this.getClass().getResourceAsStream("taskProcess.bpmn");
InputStream inputStreamPng = this.getClass().getResourceAsStream("taskProcess.png");
processEngine.getRepositoryService()//
.createDeployment()//
.addInputStream("userTask.bpmn", inputStreamBpmn)//
.addInputStream("userTask.png", inputStreamPng)//
.deploy();
// 2 启动流程
//启动流程实例,同时设置流程变量,用来指定组任务的办理人
Map<String, Object> variables = new HashMap<String, Object>();
variables.put("userIDs", "小红,小亮,小明");
ProcessInstance pi = processEngine.getRuntimeService()//
.startProcessInstanceByKey("taskProcess",variables);
System.out.println("pid:" + pi.getId());
}

分配方式三:

同样添加一个类,但是实现方法有所区别

public class TaskListenerImpl implements TaskListener {

    /**指定个人任务和组任务的办理人*/
@Override
public void notify(DelegateTask delegateTask) {
String userId1 = "小红";
String userId2 = "小亮";
//指定组任务
delegateTask.addCandidateUser(userId1);
delegateTask.addCandidateUser(userId2);
} }

最后补上一些很常用的方法

//可以分配个人任务从一个人到另一个人(认领任务)
@Test
public void setAssigneeTask(){
//任务ID
String taskId = "3408";
//指定认领的办理者
String userId = "Meixi";
processEngine.getTaskService()//
.setAssignee(taskId, userId);
} //将组任务分配给个人任务(认领任务)
@Test
public void claimTask(){
String taskId = "4008";
//个人任务的办理人
String userId = "小明";
processEngine.getTaskService().claim(taskId, userId);
} //可以分配个人任务回退到组任务,(前提之前是个组任务)
@Test
public void setAssigneeTask(){
//任务ID
String taskId = "4008";
processEngine.getTaskService()//
.setAssignee(taskId, null);
} //向组任务中添加成员
@Test
public void addUser(){
String taskId = "4008";
String userId = "小红";
processEngine.getTaskService().addCandidateUser(taskId, userId);
} //向组任务中删除成员
@Test
public void removeUser(){
String taskId = "4008";
String userId = "小亮";
processEngine.getTaskService().deleteCandidateUser(taskId, userId);
}

Activiti工作流(二)之常用操作的更多相关文章

  1. &period;Net Excel操作之NPOI(二)常用操作封装

    一.Excel数据导出常用操作 1.指定表头和描述 2.指定数据库中读出的数据集合 二.ExcelExport封装 /// <summary> /// Excel常用的表格导出逻辑封装 / ...

  2. 从零开始学Linux&lbrack;二&rsqb;:常用操作:用户组、进程、网络、ssh

    摘要:Linux基础学习:创建用户组和用户.软件包管理.磁盘管理.进程管理.前后台进程的切换.网络配置.浏览网页.远程登录ssh 第一节,主要介绍一些简单命令,这节介绍一些日常操作. 1.创建用户组和 ...

  3. RMAN备份与恢复(二)--常用操作学习

    (1)连接目标数据库 在RMAN中可以建立与目标数据库或恢复目录数据库的连接.与目标数据库连接时,用户须具有sysdba系统权限,以保证可以进行数据库的备份.修复与恢复工作. 可以在操作系统命令提示符 ...

  4. python接口自动化测试二:常用操作

    url = '接口地址' r = requests.get(url)                      # 发送get请求 print(r.status_code)               ...

  5. Activiti工作流框架学习笔记(二)之springboot2&period;0整合工作流Activiti6&period;0

    以前在工作当中做过不少与工作流Activiti有关的工作,当时都是spring集成activiti5.22的项目,现在回过头去看,其实版本已经稍微老了,因此,基于先前的工作经验,决定用较新版本的技术来 ...

  6. Redis系列(二):常用操作

    一.数据类型 如果学过数据结构就会知道,操作往往是在特定的数据结构上的,不同的数据结构就会有不同的操作,Redis支持以下的数据类型: 字符串(Strings),列表(Lists),集合(Sets), ...

  7. Hdfs常用操作

    一.linux rm是删除,不是del 二.常用操作 package hdfs; import java.io.FileInputStream; import java.io.FileNotFound ...

  8. &lbrack;Python&rsqb; re正则表达式指南以及常用操作

    一.语法 1. 使用正则表达式进行匹配的流程 2. Python支持的正则表达式元字符和语法 参考: AstralWind的Python正则表达式指南 官方文档:7.2. re — Regular e ...

  9. Linux 笔记 - 第十五章 MySQL 常用操作和 phpMyAdmin

    博客地址:http://www.moonxy.com 一.前言 前面几章介绍了 MySQL 的安装和简单的配置,只会这些还不够,作为 Linux 系统管理员,我们还需要掌握一些基本的操作,以满足日常管 ...

随机推荐

  1. IPv4组播通信原理

    2011-05-08 21:21:14 标签:组播 vin_do,vin_do学习笔记,笔记 休闲 职场 摘自网络,感谢原作者 摘要: 本文试图成为学习TCP/IP网络组播技术的入门材料.文中介绍了组 ...

  2. NPOI的使用Excel模板导出

    private string ExportScMeeting(DataTable source) { string templateFile = Server.MapPath(@"Excel ...

  3. openfire配置MSSQL说明(数据库设置)

    1.进入“SQL Server 配置管理器(SQL Server Configuration Manager)”,在左边窗口选择“SQL Server 2005网络配置”下面的分支“MSSQLServ ...

  4. python编程语言 函数的形参

    python编程语言 函数的形参的讲解: 我在交互模式中写了个函数: def adder(**args): sum=0 for x in args.keys(): sum+=args[x] retur ...

  5. Python字符串全解

    1.字符串大小写转换 def strChange(): str = "niuXinLong@163.com" print("原字符串:" + str) prin ...

  6. PL&sol;SQL第四章 where子语句

    -- 学习where语句 -- 1.学会where子句中使用常规比较符 -- 常规比较操作符:=,<>(不等于),!=,>=,<=,>,< -- 当区分大小写时,可 ...

  7. 微软SMB 3&period;0文件共享协议新特性介绍

    SMB(*nix平台和Win NT4.0又称CIFS)协议是Windows平台标准文件共享协议.Linux平台通过samba来支持.SMB最新版本v3.0,在v2.0基础上针对WAN和分布式有改进.详 ...

  8. 【火狐FireFox】同步失败后,书签被覆盖,如何恢复书签

    问题场景: 使用公司的电脑,下载安装火狐,登录个人帐号后,火狐会自动开始同步书签.但有时候会同步失败,比如登录之前选的是[本地服务],而最新的书签都是在[全球服务]理,那么很有可能同步到的是N久之前的 ...

  9. WEB安全番外第一篇--其他所谓的&OpenCurlyDoubleQuote;非主流”漏洞:URL跳转漏洞与参数污染

    一.URL跳转篇: 1.原理:先来看这段代码: <?php if(isset($_GET["url_redircetion_target"])){ $url_redirect ...

  10. 创建一个Dribbble的作品展示

    Most designers on dribbble have a personal portfolio website that usually consists of a name and a b ...