上回主要写了activiti的入门工作流之activiti7学习(一)_壹叁壹肆的博客-优快云博客这回说说Businesskey(业务标识)+ 个人任务 + 网关
启动流程实例 并添加Businesskey(业务标识)
流程定义部署在activiti后,就可以在系统中通过activiti去管理该流程的执行,执行流程表示流程的一次执行。
比如部署系统出差流程后,如果某用户要申请出差这时就需要执行这个流程,如果另外一个用户也要申请出差则也需要执行该流程,每个执行互不影响,每个执行是单独的流程实例。
启动流程实例时,指定的businesskey,就会在act_ru_execution #流程实例的执行表中存储businesskey。
Businesskey:业务标识,通常为业务表的主键,业务标识和流程实例一一对应。业务标识来源于业务系统。存储业务标识就是根据业务标识来关联查询业务系统的数据。
如图只需要点中所选的流程线上 在Condition中加上条件即可 写法 ${}
再根据流程生成对应的png图片 可以查看工作流之activiti7学习(一)_壹叁壹肆的博客-优快云博客
部署流程
@Test
public void testDeployment() {
//创建processEngine
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//得到RepositoryService实例
RepositoryService repositoryService = processEngine.getRepositoryService();
//使用repositoryService进行部署
Deployment deployment = repositoryService.createDeployment()
.addClasspathResource("demo2.bpmn")//添加bpmn资源
.addClasspathResource("demo2.bpmn.png")//添加png资源
.name("出差申请流程")
.deploy();
//输出部署信息
System.out.println("流程部署Id:" + deployment.getId());
System.out.println("流程部署名称:" + deployment.getName());
}
启动实列并对day设置参数
@Test
public void testStartProcess() {
//创建processEngine
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//获取RunTimeService
RuntimeService runtimeService = processEngine.getRuntimeService();
//流程定义的key
String key = "demo2";
//流程变量的map
Map<String, Object> variables = new HashMap<String, Object>();
//通过day来判断执行流程
variables.put("day", 4);
//启动流程
runtimeService.startProcessInstanceByKey(key, variables);
}
查看流程下一个的执行者
@Test
public void queryTask() {
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
TaskService taskService = processEngine.getTaskService();
List<Task> list = taskService.createTaskQuery().processDefinitionKey("demo2").list();
// List<Task> list = taskService.createTaskQuery().processInstanceId("62501").list();
// List<Task> list = taskService.createTaskQuery().processDefinitionId("demo5:1:57504").list();
for (Task task : list) {
System.out.println(task.getId());
System.out.println(task.getName());
System.out.println(task.getAssignee());
}
}
.执行
@Test
public void testFindPersonalTaskList() {
//任务负责人 director manager
String assignee = "work";
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//创建TaskService
TaskService taskService = processEngine.getTaskService();
//根据流程key和任务负责人查询任务。查询流程实例,有没有需要worker执行的节点
List<Task> list = taskService.createTaskQuery()
.processDefinitionKey("demo2") //可以通过流程的key来查询
// .processInstanceId("67501") //可以通过某个流程实例的id查询
// .processDefinitionId("demo5:1:65004")
.taskAssignee(assignee)
.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());
}
}
当部门经理执行完之后查看流程下一个执行会发现 由于设置的参数day=4所以下一个执行是总经理审批
个人任务
分配任务负责人
在日常开发中assignee不会写死操作
由于固定分配方式,任务只管一步一步执行任务,执行到每一个任务将按照 bpmn 的配置去分配任 务负责人。
Activiti 使用 UEL 表达式, UEL 是 java EE6 规范的一部分, UEL(Unified Expression Language)即 统一表达式语言, activiti 支持两个 UEL 表达式: UEL-value 和 UEL-method。
如图可以用表达式代替
生成png图片
部署流程
启动实列并对day以及ass设置参数
@Test
public void testStartProcess() {
//创建processEngine
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//获取RunTimeService
RuntimeService runtimeService = processEngine.getRuntimeService();
//流程定义的key
String key = "demo5";
//流程变量的map
Map<String, Object> variables = new HashMap<String, Object>();
//通过day来判断执行流程
variables.put("day", 4);
//bpmn文件中,使用uel定义的任务负责人。使用流程变量动态设置负责人
variables.put("ass1", "张三1");
variables.put("ass2", "李四1");
variables.put("ass3", "王五1");
variables.put("ass4", "赵六1");
variables.put("ass5", "胡七1");
variables.put("ass6", "朱八1");
//启动流程
runtimeService.startProcessInstanceByKey(key, variables);
}
执行
@Test
public void testFindPersonalTaskList() {
//任务负责人 director manager
String assignee = "张三1";
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//创建TaskService
TaskService taskService = processEngine.getTaskService();
//根据流程key和任务负责人查询任务。查询流程实例,有没有需要worker执行的节点
List<Task> list = taskService.createTaskQuery()
// .processDefinitionKey("demo5") //可以通过流程的key来查询
// .processInstanceId("67501") //可以通过某个流程实例的id查询
.processDefinitionId("demo5:1:65004")
.taskAssignee(assignee)
.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());
}
}
网关 用来控制流程的流向
排他网关,用来在流程中实现决策。 当流程执行到这个网关,所有分支都会判断条件是否为true,如果为true则执行该分支,
注意:排他网关只会选择一个为true的分支执行。如果有两个分支条件都为true,排他网关会选择id值较小的一条分支去执行。
并行网关允许将流程分成多条分支,也可以把多条分支汇聚到一起,并行网关的功能是基于进入和外出顺序流的
所有到达并行网关,在此等待的进入分支, 直到所有进入顺序流的分支都到达以后, 流程就会通过汇聚网关。
注意,如果同一个并行网关有多个进入和多个外出顺序流, 它就同时具有分支和汇聚功能。 这时,网关会先汇聚所有进入的顺序流,然后再切分成多个并行分支。
与其他网关的主要区别是,并行网关不会解析条件。 即使顺序流中定义了条件,也会被忽略。
包含网关
包含网关可以看做是排他网关和并行网关的结合体。
和排他网关一样,你可以在外出顺序流上定义条件,包含网关会解析它们。 但是主要的区别是包含网关可以选择多于一条顺序流,这和并行网关一样。
包含网关的功能是基于进入和外出顺序流的:
l 分支:
所有外出顺序流的条件都会被解析,结果为true的顺序流会以并行方式继续执行, 会为每个顺序流创建一个分支。
l 汇聚:
所有并行分支到达包含网关,会进入等待状态, 直到每个包含流程token的进入顺序流的分支都到达。 这是与并行网关的最大不同。换句话说,包含网关只会等待被选中执行了的进入顺序流。 在汇聚之后,流程会穿过包含网关继续执行。
流程走向如图 当day设置为4时 会走向部门经理1审批与部门经理2审批 两者都执行完之后会到排他网关,由于day>=3走向总经理审批 最后人事记录
事件网关
事件网关允许根据事件判断流向。网关的每个外出顺序流都要连接到一个中间捕获事件。 当流程到达一个基于事件网关,网关会进入等待状态:会暂停执行。与此同时,会为每个外出顺序流创建相对的事件订阅。
事件网关的外出顺序流和普通顺序流不同,这些顺序流不会真的"执行", 相反它们让流程引擎去决定执行到事件网关的流程需要订阅哪些事件。 要考虑以下条件:
-
事件网关必须有两条或以上外出顺序流;
-
事件网关后,只能使用intermediateCatchEvent类型(activiti不支持基于事件网关后连接ReceiveTask)
-
连接到事件网关的中间捕获事件必须只有一个入口顺序流。
下回见