前面介绍了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);
}

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

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


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

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

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

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

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


 当该流程启动之后,观察数据库中的表的数据

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


 然后再看ACT_RU_EXECUTION表,这张表很重要,体现了并行网关的功能


 接下来我们先完成付款和收款任务,然后再观察这两张表里面的数据


 

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


 

 可以看见这两张表中都已经没有了任何数据,尤其是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给一个人名(字符串)


 第二种就是封装成一个map传递给流程引擎

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);
}

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


 

 

 此时的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()); }
}

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

分配方式一:


 分配方式二:

//部署流程定义,启动流程实例
@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. .Net Excel操作之NPOI(二)常用操作封装

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

  2. 从零开始学Linux[二]:常用操作:用户组、进程、网络、ssh

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

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

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

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

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

  5. Activiti工作流框架学习笔记(二)之springboot2.0整合工作流Activiti6.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. [Python] re正则表达式指南以及常用操作

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

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

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

随机推荐

  1. dotnet调用node.js写的socket服务(websocket/socket/socket.io)

    https://github.com/jstott/socketio4net/tree/develop socket.io服务端node.js,.里面有js写的客户端:http://socket.io ...

  2. 使用UTF8-CPP转换unicode编码 附录:UTF8和UTF16和UTF32和Unicode编码

    本文用于解决如何用C++处理字符串的编码格式.本文采用的是成熟便捷的UTF8库来处理这个问题.首先是下载UTF8库,网址为:http://utfcpp.sourceforge.net/ 为了方便后续使 ...

  3. iOS 沙盒

    1. 概念 某个应用程序的非代码文件存放空间. 2. 文件结构 每个沙盒有三个文件夹: Documents: 存放文件 Library: 存放默认设置或状态信息.Library/caches: 缓存文 ...

  4. 测试web网站兼容性的方法

    随着操作系统,浏览器越来越多样性,导致软件兼容性测试在目前软件测试领域占有很重要的地位,无论是B/S架构还是C/S架构的软件都需要进行兼容性测试,为了充分保证产品的平台无关性,使用户充分感受到软件的友 ...

  5. 使用 Passenger +Apache扩展 Puppet,代替其Webrick的web框架

    使用 Passenger +Apache扩展 Puppet,代替其Webrick的web框架 1安装 yum install ruby-devel ruby-libs rubygems libcurl ...

  6. 内存快照排查OOM,加密时错误方法指定provider方式错误引起的OOM

    写在前面: 最近开始总结内存方面的东西,已经总结以前遇到的一些内存案例分享下,接下来还有几篇,然后是进程/线程相关的,逐渐形成我的知识体系树 如果你有兴趣,可以文章末尾的公众号二维码一起梳理这些信息. ...

  7. 模仿qq界面实现(WTL)

    前面对于界面用哪一种我试过用duilib,但是老感觉和MFC差距有点多,终于发现WTL的库能够实现我的所有界面功能,几天的努力终于搞定界面的重写.还是见我的成果吧: 1登录界面: 2主界面: 3.主界 ...

  8. GreenOpenPaint的实现(一)基本框架

    Win7下的MSPaint是Ribbon的典型运行.这种SDI程序对于图像处理来说是很适合的.利用春节时间,基于之前的积累,我实现GreenOpenPaint,主要就是模拟MSPaint的界面,实现出 ...

  9. 用反射技术替换工厂种的switch分支(14)

    首先给大家拜个晚年,祝大家新春快乐,万事如意,鸡年大吉. 好了,前面我们讲了很多的工厂模式,其中,有个很明显的特点,工厂中,有一个方法,里面有很多的swich case  分支,我们前面说过,我们可以 ...

  10. Biztalk AS2开发经验总结

    一.    准备证书    4 1.    升级win2008 R2证书服务    4 2.    申请证书    6 二.    配置证书    13 1.    为AS2配置证书    13 2. ...