flowable候選人和候選人組
之前在流程定義中的任務節點設定的負責人assignee都是固定的負責人,在流程定義設計時将參與者與檔案固定設定了,如需變更任務負責人需要修改流程定義,系統可擴充性差。
針對這種情況可以給任務設定多個候選人或者候選人組,可以從候選人中選擇參與者來完成任務。
這裡讨論的是組任務,不同于流程變量來控制任務負責人。
1 候選人
1.1 設計流程
設計一個簡單的新流程。
首先是“請假申請”,在配置設定使用者項設定兩個候選使用者。
“經理稽核”就設定一個
${assignee0}
流程變量即可。
1.2 部署流程和啟動流程執行個體
/**
* 部署流程
*/
@Test
public void deployment() {
//擷取ProcessEngine對象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//擷取RepositoryService對象,部署流程定義
RepositoryService repositoryService = processEngine.getRepositoryService();
//執行部署
repositoryService.createDeployment()
.addClasspathResource("flowable-4.bpmn20.xml")
.deploy();
}
/**
* 啟動流程
*/
@Test
public void startProcess() {
//擷取ProcessEngine對象
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//通過RuntimeService啟動流程
//通過流程定義ID啟動流程執行個體
//流程定義的ID在流程部署成功後,act_re_procdef表生成的資料主鍵ID就是流程定義ID
RuntimeService runtimeService = processEngine.getRuntimeService();
//設定候選人流程變量
Map<String, Object> variables = new HashMap<>();
variables.put("candidate0", "員工1");
variables.put("candidate1", "員工2");
ProcessInstance processInstance = runtimeService.startProcessInstanceById("flowable-4:1:10004", variables);
// 輸出相關的流程執行個體資訊
System.out.println("流程定義的ID:" + processInstance.getProcessDefinitionId());
System.out.println("流程執行個體的ID:" + processInstance.getId());
}
流程啟動後,
act_ru_variable
表可以看到候選人流程變量
act_ru_task
表的
ASSIGNEE_
字段是null
說明目前任務并沒有配置設定給任何人,無人受理
1.3 任務查詢
可以通過候選人進行查詢任務
/**
* 候選人任務查詢
*/
@Test
public void queryTaskCandidate() {
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//擷取TaskService
TaskService taskService = processEngine.getTaskService();
List<Task> taskList = taskService.createTaskQuery().processInstanceId("12501")
//設定taskCandidateUser候選人條件來查詢任務,這裡的參數值就是候選人流程變量綁定的值
//員工1和員工2都是可以查詢到資料的
.taskCandidateUser("員工1")
.list();
for (Task task : taskList) {
System.out.println("task.getId() = " + task.getId());
System.out.println("task.getName() = " + task.getName());
}
}
1.4 任務拾取
根據候選人查詢到任務後就可以拾取該任務。注意:當一個任務被拾取後,其他使用者是無法拾取該任務的。
任務拾取成功後,就會變成個人任務
/**
* 候選人拾取任務
*/
@Test
public void claimTaskCandidate() {
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//擷取TaskService
TaskService taskService = processEngine.getTaskService();
Task task = taskService.createTaskQuery().processInstanceId("12501")
//設定taskCandidateUser候選人條件來查詢任務,這裡的參數值就是候選人流程變量綁定的值
//員工1和員工2都是可以查詢到資料的
.taskCandidateUser("員工1")
.singleResult();
if (task != null) {
/**
* 拾取任務
* 即使該使用者不是任務的候選人也可以拾取任務,建議拾取時做校驗,根據候選人查詢
* 任務拾取成功後,就會變成個人任務,之後的操作就和之前一樣了,complete即可
*/
taskService.claim(task.getId(), "員工1");
}
}
說明:即使不是任務的候選人也可以進行拾取任務,是以需要根據任務候選人去查詢任務再去進行拾取
1.5 任務歸還
如果任務拾取之後不想操作或者誤拾取任務也可以進行歸還任務。
/**
* 任務歸還
*/
@Test
public void unClaimTaskCandidate() {
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//擷取TaskService
TaskService taskService = processEngine.getTaskService();
Task task = taskService.createTaskQuery().processInstanceId("12501")
//員工1拾取的任務,需要通過員工1查詢
.taskAssignee("員工1")
.singleResult();
if (task != null) {
taskService.unclaim(task.getId());
}
}
任務成功歸還後,
ASSIGNEE_
就會為null,需要由任務候選人重新拾取
1.6 任務交接
如果任務拾取後,不想操作也不想歸還,可以交接給他人進行處理。
/**
* 任務交接
*/
@Test
public void taskCandidate() {
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//擷取TaskService
TaskService taskService = processEngine.getTaskService();
Task task = taskService.createTaskQuery().processInstanceId("12501")
//員工1拾取的任務,需要通過員工1查詢
.taskAssignee("員工1")
.singleResult();
if (task != null) {
/**
* 任務交接,就是更新任務的配置設定人字段
* 由于可配置設定給任意的人員,是以建議實際開發中做判斷處理,隻将任務配置設定給候選人
*/
taskService.setAssignee(task.getId(), "員工3");
}
}
1.7 任務完成
就是之前正常處理流程,調用complete方法
/**
* 任務完成
*/
@Test
public void taskComplete() {
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//擷取TaskService
TaskService taskService = processEngine.getTaskService();
Task task = taskService.createTaskQuery().processInstanceId("12501")
.taskAssignee("員工3")
.singleResult();
if (task != null) {
//流程設計的時候,經理審批有個`assignee0`流程變量,是以這裡設定下
Map<String, Object> variables = new HashMap<>();
variables.put("assignee0", "經理");
taskService.complete(task.getId(), variables);
}
}
2 候選人組
當候選人很多的情況下,我們可以分組來處理。先建立組,然後把使用者配置設定到這個組中。
2.1 管理使用者群組
2.1.1 使用者管理
通過
act_id_user
表維護使用者
/**
* 維護使用者
*/
@Test
public void createUser() {
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
// 通過 IdentityService 完成相關的使用者群組的管理
IdentityService identityService = processEngine.getIdentityService();
User user = null;
for (int i = 1; i <= 3; i++) {
user = identityService.newUser("員工" + i);
user.setFirstName(i+"");
user.setEmail(i+"@qq.com");
identityService.saveUser(user);
}
}
2.1.2 使用者組管理
通過
act_id_group
表維護
/**
* 維護使用者組
*/
@Test
public void createGroup() {
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
// 通過 IdentityService 完成相關的使用者群組的管理
IdentityService identityService = processEngine.getIdentityService();
Group group = identityService.newGroup("group1");
group.setName("研發部");
group.setType("1");
identityService.saveGroup(group);
}
2.1.3 使用者和使用者組關聯
通過
act_id_membership
表維護
/**
* 使用者和使用者組關聯
*/
@Test
public void userGroup() {
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
IdentityService identityService = processEngine.getIdentityService();
// 根據組的編号找到對應的Group對象
Group group = identityService.createGroupQuery().groupId("group1").singleResult();
//找到使用者
List<User> users = identityService.createUserQuery().list();
for (User user : users) {
//使用者配置設定給使用者組
identityService.createMembership(user.getId(), group.getId());
}
}
2.2 候選人組應用
使用者和使用者組的建立及關聯搞清楚後,就可以使用候選人組實作流程任務配置設定了
2.2.1 設計流程
設計一個新的流程。
2.2.2 部署流程和啟動流程執行個體
/**
* 部署流程
*/
@Test
public void deployment() {
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
RepositoryService repositoryService = processEngine.getRepositoryService();
repositoryService.createDeployment().addClasspathResource("flowable-5.bpmn20.xml").name("候選人組流程").deploy();
}
/**
* 啟動流程
*/
@Test
public void startProcess() {
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
RuntimeService runtimeService = processEngine.getRuntimeService();
//查詢到使用者組
IdentityService identityService = processEngine.getIdentityService();
Group group = identityService.createGroupQuery().groupId("group1").singleResult();
//然後給流程設計裡面的${group1}流程變量指派
Map<String, Object> variables = new HashMap<>();
variables.put("group1", group.getId());
runtimeService.startProcessInstanceById("flowable-5:1:32504", variables);
}
act_ru_identitylink
表中可以看到流程任務綁定的候選人組
2.2.3 任務的拾取和完成
/**
* 查詢候選人組任務
*/
@Test
public void queryTaskCandidateGroup() {
//擷取ProcessEngine引擎
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//根據使用者擷取候選組
IdentityService identityService = processEngine.getIdentityService();
Group group = identityService.createGroupQuery().groupMember("員工1").singleResult();
//擷取組任務
TaskService taskService = processEngine.getTaskService();
List<Task> taskList = taskService.createTaskQuery()
.processInstanceId("35001")
.taskCandidateGroup(group.getId())
.list();
for (Task task : taskList) {
System.out.println("task.getId() = " + task.getId());
System.out.println("task.getName() = " + task.getName());
}
}
/**
* 拾取組任務
* 就是通過候選組綁定查詢出來的任務,然後拾取,和普通的流程任務操作一樣
* 正常業務開發下,該組下的任務隻能由該組人員拾取
* 拾取之後,不想操作的話也可以退還或者交接給他人
*/
@Test
public void claimTaskCandidate() {
//擷取ProcessEngine引擎
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//根據使用者擷取候選組
IdentityService identityService = processEngine.getIdentityService();
Group group = identityService.createGroupQuery().groupMember("員工1").singleResult();
//擷取組任務
TaskService taskService = processEngine.getTaskService();
List<Task> taskList = taskService.createTaskQuery()
.processInstanceId("35001")
.taskCandidateGroup(group.getId())
.list();
for (Task task : taskList) {
System.out.println("task.getId() = " + task.getId());
System.out.println("task.getName() = " + task.getName());
//拾取
taskService.claim(task.getId(), "員工1");
System.out.println("任務:"+task.getName()+"拾取成功");
}
}
/**
* 完成組任務
* 就是完成正常的一個流程任務
*/
@Test
public void completeTask() {
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
TaskService taskService = processEngine.getTaskService();
Task task = taskService.createTaskQuery().processInstanceId("35001").taskAssignee("員工1").singleResult();
Assert.assertNotNull(task);
//流程設計的時候有個assignee0流程變量,這裡需要設定下
Map<String, Object> variables = new HashMap<>();
variables.put("assignee0", "經理");
taskService.complete(task.getId(), variables);
}
啟動流程執行個體之後,查詢目前任務執行表:
記錄了目前執行的任務,由于該任務是組任務,
assignee_
字段值是null,讓拾取任務之後該字段才會有拾取使用者的資訊。
查詢任務參與者:
select * from act_ru_identitylink
記錄了參與任務使用者或組,目前任務如果設定了候選人,就會向該表插入候選人記錄,有幾個候選人就插入幾條記錄,與
act_ru_identitylink
對應的還有一張曆史表
act_hi_identitylink
,向
act_ru_identitylink
插入記錄的同時也會向
act_hi_identitylink
插入記錄。