1. 设计流程图
2. Bpmn文件
填写请假单:使用流程变量,指定当前登录的人未任务执行者
项目经理审批:小于等于3天,为一个角色,可以有多个人可以进行审批,项目中设置为(王一,王二,王三)
总经理审批:大于3天,只有一个总经理,指定一个人进行审批,项目中设置为(王大)
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:activiti="http://activiti.org/bpmn" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC" xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI" xmlns:tns="http://www.activiti.org/test" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" expressionLanguage="http://www.w3.org/1999/XPath" id="m1596608849637" name="" targetNamespace="http://www.activiti.org/test" typeLanguage="http://www.w3.org/2001/XMLSchema">
<process id="leave" isClosed="false" isExecutable="true" processType="None">
<startEvent id="_2" name="开始"/>
<userTask activiti:assignee="${inputUser}" activiti:exclusive="true" id="_3" name="填写请假单"/>
<exclusiveGateway gatewayDirection="Unspecified" id="_4" name="排他网关"/>
<userTask activiti:assignee="王大" activiti:exclusive="true" id="_5" name="总经理审批"/>
<userTask activiti:candidateUsers="王一,王二,王三" activiti:exclusive="true" id="_6" name="项目经理审批">
</userTask>
<endEvent id="_7" name="结束"/>
<sequenceFlow id="_8" sourceRef="_2" targetRef="_3"/>
<sequenceFlow id="_9" sourceRef="_3" targetRef="_4"/>
<sequenceFlow id="_10" name="大于三天" sourceRef="_4" targetRef="_5">
<conditionExpression xsi:type="tFormalExpression"><![CDATA[${day>3}]]></conditionExpression>
</sequenceFlow>
<sequenceFlow id="_11" name="小于三天" sourceRef="_4" targetRef="_6">
<conditionExpression xsi:type="tFormalExpression"><![CDATA[${day<=3}]]></conditionExpression>
</sequenceFlow>
<sequenceFlow id="_12" sourceRef="_5" targetRef="_7"/>
<sequenceFlow id="_13" sourceRef="_6" targetRef="_7"/>
</process>
<bpmndi:BPMNDiagram documentation="background=#000000;count=1;horizontalcount=1;orientation=0;width=842.4;height=1195.2;imageableWidth=832.4;imageableHeight=1185.2;imageableX=5.0;imageableY=5.0" id="Diagram-_1" name="New Diagram">
<bpmndi:BPMNPlane bpmnElement="leave">
<bpmndi:BPMNShape bpmnElement="_2" id="Shape-_2">
<omgdc:Bounds height="32.0" width="32.0" x="0.0" y="345.0"/>
<bpmndi:BPMNLabel>
<omgdc:Bounds height="32.0" width="32.0" x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="_3" id="Shape-_3">
<omgdc:Bounds height="55.0" width="85.0" x="90.0" y="335.0"/>
<bpmndi:BPMNLabel>
<omgdc:Bounds height="55.0" width="85.0" x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="_4" id="Shape-_4" isMarkerVisible="false">
<omgdc:Bounds height="32.0" width="32.0" x="250.0" y="345.0"/>
<bpmndi:BPMNLabel>
<omgdc:Bounds height="32.0" width="32.0" x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="_5" id="Shape-_5">
<omgdc:Bounds height="55.0" width="85.0" x="375.0" y="280.0"/>
<bpmndi:BPMNLabel>
<omgdc:Bounds height="55.0" width="85.0" x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="_6" id="Shape-_6">
<omgdc:Bounds height="55.0" width="85.0" x="370.0" y="415.0"/>
<bpmndi:BPMNLabel>
<omgdc:Bounds height="55.0" width="85.0" x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="_7" id="Shape-_7">
<omgdc:Bounds height="32.0" width="32.0" x="555.0" y="350.0"/>
<bpmndi:BPMNLabel>
<omgdc:Bounds height="32.0" width="32.0" x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge bpmnElement="_13" id="BPMNEdge__13" sourceElement="_6" targetElement="_7">
<omgdi:waypoint x="455.0" y="442.5"/>
<omgdi:waypoint x="555.0" y="366.0"/>
<bpmndi:BPMNLabel>
<omgdc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="_12" id="BPMNEdge__12" sourceElement="_5" targetElement="_7">
<omgdi:waypoint x="460.0" y="307.5"/>
<omgdi:waypoint x="555.0" y="366.0"/>
<bpmndi:BPMNLabel>
<omgdc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="_8" id="BPMNEdge__8" sourceElement="_2" targetElement="_3">
<omgdi:waypoint x="32.0" y="361.0"/>
<omgdi:waypoint x="90.0" y="362.5"/>
<bpmndi:BPMNLabel>
<omgdc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="_9" id="BPMNEdge__9" sourceElement="_3" targetElement="_4">
<omgdi:waypoint x="175.0" y="362.5"/>
<omgdi:waypoint x="250.0" y="361.0"/>
<bpmndi:BPMNLabel>
<omgdc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="_11" id="BPMNEdge__11" sourceElement="_4" targetElement="_6">
<omgdi:waypoint x="282.0" y="361.0"/>
<omgdi:waypoint x="370.0" y="442.5"/>
<bpmndi:BPMNLabel>
<omgdc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="_10" id="BPMNEdge__10" sourceElement="_4" targetElement="_5">
<omgdi:waypoint x="282.0" y="361.0"/>
<omgdi:waypoint x="375.0" y="307.5"/>
<bpmndi:BPMNLabel>
<omgdc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/>
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</definitions>
3. 测试类
package com.yb;
import com.yb.domain.User;
import org.activiti.engine.HistoryService;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.IdentityLink;
import org.activiti.engine.task.Task;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.List;
/**
* @author liangjie@itcast.cn
* @version 1.0
* @date 2020/8/5
*/
@RunWith(SpringRunner.class)
@SpringBootTest
public class ActivitiJpaTest02 {
@Resource
private RepositoryService repositoryService;
@Resource
private RuntimeService runtimeService;
@Resource
private TaskService taskService;
@Resource
private HistoryService historyService;
@Resource
private HttpServletRequest request;
/**
* 部署流程,
*/
@Test
public void repositoryDeploy(){
Deployment deploy = repositoryService.createDeployment()
.addClasspathResource("processes/activiti_leave.bpmn")
.addClasspathResource("processes/activiti_leave.png")
.name("测试一个角色多人审批01")
.deploy();
System.out.println("部署ID:"+deploy.getId());
System.out.println("部署名称"+deploy.getName());
}
/**
* 发布流程
*/
@Test
public void runtimeRelease(){
// User user = (User) request.getServletContext().getAttribute("user");
// 模拟登录用户,进行指定任务人
User user = new User(1, "jack", "1234");
HashMap<String, Object> map = new HashMap<>();
map.put("inputUser",user.getUsername());
ProcessInstance pi = runtimeService.startProcessInstanceByKey("leave",map);
System.out.println("流程实例ID:"+pi.getId());
System.out.println("流程定义ID:"+pi.getProcessDefinitionId());
}
/**
* 查询及完成任务
*/
@Test
public void taskQueryComplete(){
// User user = (User) request.getServletContext().getAttribute("user");
// 模拟登录用户,获取到任务人,进行任务的查询和提交
List<Task> list = taskService.createTaskQuery()
.taskAssignee("jack")
.list();
for (Task task : list) {
System.out.println("--------------------------------------------");
System.out.println("任务ID:" + task.getId());
System.out.println("任务名称:" + task.getName());
System.out.println("任务创建时间:" + task.getCreateTime());
System.out.println("任务委派人:" + task.getAssignee());
System.out.println("流程实例ID:" + task.getProcessInstanceId());
//完成任务,这里测试请假3天触发一个角色多个审批人
HashMap<String, Object> map = new HashMap<>();
map.put("day",3);
taskService.complete(task.getId(),map);
}
}
/**
* 测试通过待办任务获取到属于该任务角色id的审批人都有哪些
*/
@Test
public void testMultiple(){
//Approval approval
//模拟获取到前台传来的待办任务的id,这里是5005
//获取到运行时act_ru_identitylink中的数据
List<IdentityLink> taskList = taskService.getIdentityLinksForTask("5005");
//遍历取出数据
for (IdentityLink identityLink : taskList) {
System.out.println(identityLink.getGroupId()+"==审批人名称:"+identityLink.getUserId()
+"==对应审批角色的ID"+identityLink.getTaskId());
}
}
/**
*为审批人拾取任务,这样才能提交任务
*/
@Test
public void claimTask(){
//上面获取到的
String taskId="5005";
String userId="王一";
//拾取任务
taskService.claim(taskId,userId);
//任务拾取以后, 可以回退给组
//taskService.setAssignee(taskId, null);
//任务拾取以后,可以转给别人去处理(别人可以是组成员也可以不是)
//taskService.claim(taskId, "wangliu");
}
/**
* 查询及完成任务
*/
@Test
public void taskQueryComplete2(){
List<Task> list = taskService.createTaskQuery()
.taskAssignee("王一")
.list();
for (Task task : list) {
System.out.println("--------------------------------------------");
System.out.println("任务ID:" + task.getId());
System.out.println("任务名称:" + task.getName());
System.out.println("任务创建时间:" + task.getCreateTime());
System.out.println("任务委派人:" + task.getAssignee());
System.out.println("流程实例ID:" + task.getProcessInstanceId());
//完成任务,王一进行审批
taskService.complete(task.getId());
}
}
}
3.1 部署启动流程
3.2 完成请假单的提交
请假单提交完成后,排他网关判断请假天数3天,项目经理审批,数据库如下:
由数据库可以看出当前任务没有指派审批人,那么这个角色的审批人在那里呢?
在act_ru_identitylink表中
这个表中对应任务id的有三个人可以进行审批,分别是王一,王二,王三。
3.3 获取该角色的所有审批人
3.4 为审批人拾取任务
任务拾取后,该待办任务就由王一处理,数据库待办任务如下:
可以看到原来没有处理人,现在经过拾取后,该任务就有了办理人。
3.5 完成任务
任务完成,act_ru_identitylink表和act_ru_task表,数据清空,流程结束,历史表如下:
到此,一个角色多人审批的入门测试学习结束。