---為了加深對activiti的理解記憶,對自己做的一個流程進行自述。加強記憶
請假實例
一.設計請假的流程圖以及流程文件,完善對應數據項,比如用戶信息,請假單信息
--請假單
--流程圖
--流程文件leaveBill.bpmn
<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" 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" typeLanguage="http://www.w3.org/2001/XMLSchema" expressionLanguage="http://www.w3.org/1999/XPath" targetNamespace="http://www.activiti.org/test">
<process id="LeaveBill" name="LeaveBillProcess" isExecutable="true">
<startEvent id="startevent1" name="Start"></startEvent>
<userTask id="usertask1" name="提交申請" activiti:assignee="${inputUser}" activiti:formKey="workflowAction_audit.action"></userTask>
<sequenceFlow id="flow1" sourceRef="startevent1" targetRef="usertask1"></sequenceFlow>
<userTask id="usertask2" name="經紀人審批" activiti:formKey="workflowAction_audit.action">
<extensionElements>
<activiti:taskListener event="create" class="cn.itcast.ssh.utils.MangerTaskHandlerCandidateUsers"></activiti:taskListener>
</extensionElements>
</userTask>
<sequenceFlow id="flow2" sourceRef="usertask1" targetRef="usertask2"></sequenceFlow>
<userTask id="usertask3" name="老總審批" activiti:assignee="王中軍" activiti:formKey="workflowAction_audit.action"></userTask>
<sequenceFlow id="flow3" sourceRef="usertask2" targetRef="usertask3"></sequenceFlow>
<endEvent id="endevent1" name="End"></endEvent>
<sequenceFlow id="flow4" sourceRef="usertask3" targetRef="endevent1"></sequenceFlow>
</process>
<bpmndi:BPMNDiagram id="BPMNDiagram_LeaveBill">
<bpmndi:BPMNPlane bpmnElement="LeaveBill" id="BPMNPlane_LeaveBill">
<bpmndi:BPMNShape bpmnElement="startevent1" id="BPMNShape_startevent1">
<omgdc:Bounds height="35.0" width="35.0" x="290.0" y="60.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="usertask1" id="BPMNShape_usertask1">
<omgdc:Bounds height="55.0" width="105.0" x="255.0" y="140.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="usertask2" id="BPMNShape_usertask2">
<omgdc:Bounds height="55.0" width="105.0" x="255.0" y="230.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="usertask3" id="BPMNShape_usertask3">
<omgdc:Bounds height="55.0" width="105.0" x="255.0" y="310.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape bpmnElement="endevent1" id="BPMNShape_endevent1">
<omgdc:Bounds height="35.0" width="35.0" x="290.0" y="400.0"></omgdc:Bounds>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge bpmnElement="flow1" id="BPMNEdge_flow1">
<omgdi:waypoint x="307.0" y="95.0"></omgdi:waypoint>
<omgdi:waypoint x="307.0" y="140.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="flow2" id="BPMNEdge_flow2">
<omgdi:waypoint x="307.0" y="195.0"></omgdi:waypoint>
<omgdi:waypoint x="307.0" y="230.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="flow3" id="BPMNEdge_flow3">
<omgdi:waypoint x="307.0" y="285.0"></omgdi:waypoint>
<omgdi:waypoint x="307.0" y="310.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge bpmnElement="flow4" id="BPMNEdge_flow4">
<omgdi:waypoint x="307.0" y="365.0"></omgdi:waypoint>
<omgdi:waypoint x="307.0" y="400.0"></omgdi:waypoint>
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</definitions>
二.准備請假單的增刪改查頁面,用來處理請假單的生成業務邏輯
填寫好請假單后,就要開始申請請假了。這里主要是更新請假狀態,啟動請假流程實例。runtimeService.startProcessInstanceByKey(key,objId,variables);key時請假實體類的類名,其實就是一個標識。這里還可以通過流程id來啟動startProcessInstanceById
/**更新請假狀態,啟動流程實例,讓啟動的流程實例關聯業務*/
@Override
public void saveStartProcess(WorkflowBean workflowBean) {
//1:獲取請假單ID,使用請假單ID,查詢請假單的對象LeaveBill
Long id = workflowBean.getId();
LeaveBill leaveBill = leaveBillDao.findLeaveBillById(id);
//2:更新請假單的請假狀態從0變成1(初始錄入-->審核中)
leaveBill.setState(1);
//3:使用當前對象獲取到流程定義的key(對象的名稱就是流程定義的key)
String key = leaveBill.getClass().getSimpleName();
/**
* 4:從Session中獲取當前任務的辦理人,使用流程變量設置下一個任務的辦理人
* inputUser是流程變量的名稱,
* 獲取的辦理人是流程變量的值
*/
Map<String, Object> variables = new HashMap<String,Object>();
variables.put("inputUser", SessionContext.get().getName());//表示惟一用戶
/**
* 5: (1)使用流程變量設置字符串(格式:LeaveBill.id的形式),通過設置,讓啟動的流程(流程實例)關聯業務
(2)使用正在執行對象表中的一個字段BUSINESS_KEY(Activiti提供的一個字段),讓啟動的流程(流程實例)關聯業務
*/
//格式:LeaveBill.id的形式(使用流程變量)
String objId = key+"."+id;
variables.put("objId", objId);
//6:使用流程定義的key,啟動流程實例,同時設置流程變量,同時向正在執行的執行對象表中的字段BUSINESS_KEY添加業務數據,同時讓流程關聯業務
runtimeService.startProcessInstanceByKey(key,objId,variables);
}
三.啟動以后,流程框架會按照你畫好的流程圖,走到第一個節點,這里說的是除了start節點。也就是申請請假節點。這里設置的申請請假處理人,是當前登錄人。隨意,當我們啟動請假流程后,我們也就有了一個任務,提交申請的任務。查看我們的任務:
/**2:使用當前用戶名查詢正在執行的任務表,獲取當前任務的集合List<Task>*/
@Override
public List<Task> findTaskListByName(String name) {
List<Task> list = taskService.createTaskQuery()//
.taskAssignee(name)//指定個人任務查詢
.orderByTaskCreateTime().asc()//
.list();
if(null==list||list.size()<1){//如果指定個人任務為空,則查詢多人任務
list = taskService.createTaskQuery().
taskCandidateUser(name).
orderByTaskCreateTime().
asc().
list();
}
if(null==list||list.size()<1){//如果指定多人任務為空在獲取組的任務
list = taskService.createTaskQuery().taskCandidateGroup(name).
orderByTaskCreateTime().
asc().
list();
}
return list;
}
---處理我們的任務,使其想下一個節點進行
public String audit(){
//獲取任務ID
String taskId = workflowBean.getTaskId();
/**一:使用任務ID,查找請假單ID,從而獲取請假單信息*/
LeaveBill leaveBill = workflowService.findLeaveBillByTaskId(taskId);
ValueContext.putValueStack(leaveBill);
/**二:已知任務ID,查詢ProcessDefinitionEntiy對象,從而獲取當前任務完成之后的連線名稱,並放置到List<String>集合中*/
List<String> outcomeList = workflowService.findOutComeListByTaskId(taskId);
ValueContext.putValueContext("outcomeList", outcomeList);
/**三:查詢所有歷史審核人的審核信息,幫助當前人完成審核,返回List<Comment>*/
List<Comment> commentList = workflowService.findCommentByTaskId(taskId);
ValueContext.putValueContext("commentList", commentList);
return "taskForm";
}
------獲取后續流程節點的信息
/**二:已知任務ID,查詢ProcessDefinitionEntiy對象,從而獲取當前任務完成之后的連線名稱,並放置到List<String>集合中*/
@Override
public List<String> findOutComeListByTaskId(String taskId) {
//返回存放連線的名稱集合
List<String> list = new ArrayList<String>();
//1:使用任務ID,查詢任務對象
Task task = taskService.createTaskQuery()//
.taskId(taskId)//使用任務ID查詢
.singleResult();
//2:獲取流程定義ID
String processDefinitionId = task.getProcessDefinitionId();
//3:查詢ProcessDefinitionEntiy對象
ProcessDefinitionEntity processDefinitionEntity = (ProcessDefinitionEntity) repositoryService.getProcessDefinition(processDefinitionId);
//使用任務對象Task獲取流程實例ID
String processInstanceId = task.getProcessInstanceId();
//使用流程實例ID,查詢正在執行的執行對象表,返回流程實例對象
ProcessInstance pi = runtimeService.createProcessInstanceQuery()//
.processInstanceId(processInstanceId)//使用流程實例ID查詢
.singleResult();
//獲取當前活動的id
String activityId = pi.getActivityId();
//4:獲取當前的活動
ActivityImpl activityImpl = processDefinitionEntity.findActivity(activityId);
//5:獲取當前活動完成之后連線的名稱
List<PvmTransition> pvmList = activityImpl.getOutgoingTransitions();
if(pvmList!=null && pvmList.size()>0){
for(PvmTransition pvm:pvmList){
String name = (String) pvm.getProperty("name");
if(StringUtils.isNotBlank(name)){
list.add(name);
}
else{
list.add("默認提交");
}
}
}
return list;
}
-------獲取完后通過任務id獲取歷史批注信息
/**獲取批注信息,傳遞的是當前任務ID,獲取歷史任務ID對應的批注*/
@Override
public List<Comment> findCommentByTaskId(String taskId) {
List<Comment> list = new ArrayList<Comment>();
//使用當前的任務ID,查詢當前流程對應的歷史任務ID
//使用當前任務ID,獲取當前任務對象
Task task = taskService.createTaskQuery()//
.taskId(taskId)//使用任務ID查詢
.singleResult();
//獲取流程實例ID
String processInstanceId = task.getProcessInstanceId();
//使用流程實例ID,查詢歷史任務,獲取歷史任務對應的每個任務ID
List<HistoricTaskInstance> htiList = historyService.createHistoricTaskInstanceQuery()//歷史任務表查詢
.processInstanceId(processInstanceId)//使用流程實例ID查詢
.list();
//遍歷集合,獲取每個任務ID
if(htiList!=null && htiList.size()>0){
for(HistoricTaskInstance hti:htiList){
//任務ID
String htaskId = hti.getId();
//獲取批注信息
List<Comment> taskList = taskService.getTaskComments(htaskId);//對用歷史完成后的任務ID
list.addAll(taskList);
}
}
list = taskService.getProcessInstanceComments(processInstanceId);
return list;
}
----以上信息用來展現將來任務進行的狀態,流程圖的查看
四.提交申請,進入下一環節
/**指定連線的名稱完成任務*/
@Override
public void saveSubmitTask(WorkflowBean workflowBean) {
//獲取任務ID
String taskId = workflowBean.getTaskId();
//獲取連線的名稱
String outcome = workflowBean.getOutcome();
//批注信息
String message = workflowBean.getComment();
//獲取請假單ID
Long id = workflowBean.getId();
/**
* 1:在完成之前,添加一個批注信息,向act_hi_comment表中添加數據,用於記錄對當前申請人的一些審核信息
*/
//使用任務ID,查詢任務對象,獲取流程流程實例ID
Task task = taskService.createTaskQuery()//
.taskId(taskId)//使用任務ID查詢
.singleResult();
//獲取流程實例ID
String processInstanceId = task.getProcessInstanceId();
/**
* 注意:添加批注的時候,由於Activiti底層代碼是使用:
* String userId = Authentication.getAuthenticatedUserId();
CommentEntity comment = new CommentEntity();
comment.setUserId(userId);
所有需要從Session中獲取當前登錄人,作為該任務的辦理人(審核人),對應act_hi_comment表中的User_ID的字段,不過不添加審核人,該字段為null
所以要求,添加配置執行使用Authentication.setAuthenticatedUserId();添加當前任務的審核人
* */
Authentication.setAuthenticatedUserId(SessionContext.get().getName());
taskService.addComment(taskId, processInstanceId, message);
/**
* 2:如果連線的名稱是“默認提交”,那么就不需要設置,如果不是,就需要設置流程變量
* 在完成任務之前,設置流程變量,按照連線的名稱,去完成任務
流程變量的名稱:outcome
流程變量的值:連線的名稱
*/
Map<String, Object> variables = new HashMap<String,Object>();
if(outcome!=null && !outcome.equals("默認提交")){
variables.put("outcome", outcome);
}
//3:使用任務ID,完成當前人的個人任務,同時流程變量
taskService.complete(taskId, variables);
//4:當任務完成之后,需要指定下一個任務的辦理人(使用類)-----已經開發完成
/**
* 5:在完成任務之后,判斷流程是否結束
如果流程結束了,更新請假單表的狀態從1變成2(審核中-->審核完成)
*/
ProcessInstance pi = runtimeService.createProcessInstanceQuery()//
.processInstanceId(processInstanceId)//使用流程實例ID查詢
.singleResult();
//流程結束了
if(pi==null){
//更新請假單表的狀態從1變成2(審核中-->審核完成)
LeaveBill bill = leaveBillDao.findLeaveBillById(id);
bill.setState(2);
}
}
五.接下來的老總審批和4是完全相同的重復步驟了。不做解釋了
走到最后節點時,流程實例ProcessInstance會為空,則進行業務邏輯處理。完成請假單的所有流程。到這里就結束了。
工作流的運作軌跡,都在代碼中,注釋的很清楚。