以前在圖書館看到過很多關於Activiti的書籍,但是不知道他是幹什麼的,只知道這玩意和Android中的Activity就差一個單詞,天真的以為以後也用不上,殊不知,在實習第一天就被讓學習Activiti,經過兩天的研究,終於有了些眉目,所以在此記錄下來,下面將會展示兩個小案例,以此來入個門。
Activiti簡介Activiti是一個輕量級以Java為中心的開源BPMN引擎,可以釋出設計好的流程定義,並透過api進行流程排程,滿足現實世界中的流程自動化需求。
而BPMN是一種流程建模的通用和標準語言,用來繪製業務流程圖,以便更好地讓各部門之間理解業務流程和相互關係,旨在促進業務流程的溝通和理解。
對於Java開發者來說,Activiti的首席架構師Tom Baeyens曾提到,Activiti的首個目標就是要獲得開發者的青睞。首先它在使用時極為方便,只是個jar檔案,使用時僅需要將其放在類路徑中,當然,Activiti也可以作為獨立伺服器的方式使用,同時Activiti提供了很多 BPM高階工具,其中還包括開發了協作工具,使得開發人員、業務人員和運維人員能夠更好的協同工作。
以下是Activiti各個服務的功能簡介:
RepositoryService: Activiti 中每一個不同版本的業務流程的定義都需要使用一些定義檔案,部署檔案和支援資料 ( 例如 BPMN2.0 XML 檔案,表單定義檔案,流程定義影象檔案等 ),這些檔案都儲存在 Activiti 內建的 Repository 中。Repository Service 提供了對 repository 的存取服務。RuntimeService:在 Activiti 中,每當一個流程定義被啟動一次之後,都會生成一個相應的流程物件例項。Runtime Service 提供了啟動流程、查詢流程例項、設定獲取流程例項變數等功能。此外它還提供了對流程部署,流程定義和流程例項的存取服務。TaskService:在 Activiti 中業務流程定義中的每一個執行節點被稱為一個 Task,對流程中的資料存取,狀態變更等操作均需要在 Task 中完成。Task Service 提供了對使用者 Task 和 Form 相關的操作。它提供了執行時任務查詢、領取、完成、刪除以及變數設定等功能。IdentityService:Activiti 中內建了使用者以及組管理的功能,必須使用這些使用者和組的資訊才能獲取到相應的 Task。Identity Service 提供了對 Activiti 系統中的使用者和組的管理功能。ManagementService:Management Service 提供了對 Activiti 流程引擎的管理和維護功能,這些功能不在工作流驅動的應用程式中使用,主要用於 Activiti 系統的日常維護。HistoryService: History Service 用於獲取正在執行或已經完成的流程例項的資訊,與 Runtime Service 中獲取的流程資訊不同,歷史資訊包含已經持久化儲存的永久資訊,並已經被針對查詢最佳化。FormService: Activiti 中的流程和狀態 Task 均可以關聯業務相關的資料。透過使用 Form Service 可以存取啟動和完成任務所需的表單資料並且根據需要來渲染表單。(工作流總是以任務(Task)的形式驅動人處理業務或者驅動業務系統自動完成作業。)
BPMN流程定義設計BMPN工作流程圖可以使用官方提供的一個工具,下載後將他放在tomcat的webapps下,然後啟動tomcat,下面是登入介面,使用者名稱和密碼分別是admin、test。
進入之後選第一個,然後Create Process。
接下來我們做一個簡單的流程,現在假設小明晚上回家後先做作業,然後打遊戲,按照這個流程我們來寫一個程式。
繪製好之後我們將他下載下來,是一個xml格式的,具體如何下載,這裡就不說了,然後將他放在resources/processes路徑下,activiti-app這個工具其實就是用來生成下面這些資料的。
activiti-test.bpmn20.xml內容如下:
<?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/processdef"> <process id="activiti-test" name="activiti-test" isExecutable="true"> <documentation>activiti-test</documentation> <startEvent id="start" name="開始"></startEvent> <endEvent id="end" name="結束"></endEvent> <userTask id="user_task1" name="寫作業" activiti:assignee="${user}"></userTask> <userTask id="user_task2" name="打遊戲" activiti:assignee="${user}"></userTask> <sequenceFlow id="sid-50EF2A93-83CE-44ED-AA41-F1A8F7ADE00C" sourceRef="start" targetRef="user_task1"></sequenceFlow> <sequenceFlow id="sid-5E51BC0F-5775-4727-8DD4-5325575BAC7B" sourceRef="user_task1" targetRef="user_task2"></sequenceFlow> <sequenceFlow id="sid-9CC4C5EC-9D5E-47F3-BEF4-94D268E004E0" sourceRef="user_task2" targetRef="end"></sequenceFlow> </process> <bpmndi:BPMNDiagram id="BPMNDiagram_activiti-test"> <bpmndi:BPMNPlane bpmnElement="activiti-test" id="BPMNPlane_activiti-test"> <bpmndi:BPMNShape bpmnElement="start" id="BPMNShape_start"> <omgdc:Bounds height="30.0" width="30.0" x="100.0" y="163.0"></omgdc:Bounds> </bpmndi:BPMNShape> <bpmndi:BPMNShape bpmnElement="end" id="BPMNShape_end"> <omgdc:Bounds height="28.0" width="28.0" x="662.5" y="164.0"></omgdc:Bounds> </bpmndi:BPMNShape> <bpmndi:BPMNShape bpmnElement="user_task1" id="BPMNShape_user_task1"> <omgdc:Bounds height="80.0" width="100.0" x="236.5" y="138.0"></omgdc:Bounds> </bpmndi:BPMNShape> <bpmndi:BPMNShape bpmnElement="user_task2" id="BPMNShape_user_task2"> <omgdc:Bounds height="80.0" width="100.0" x="435.0" y="138.0"></omgdc:Bounds> </bpmndi:BPMNShape> <bpmndi:BPMNEdge bpmnElement="sid-9CC4C5EC-9D5E-47F3-BEF4-94D268E004E0" id="BPMNEdge_sid-9CC4C5EC-9D5E-47F3-BEF4-94D268E004E0"> <omgdi:waypoint x="535.0" y="178.0"></omgdi:waypoint> <omgdi:waypoint x="662.5" y="178.0"></omgdi:waypoint> </bpmndi:BPMNEdge> <bpmndi:BPMNEdge bpmnElement="sid-5E51BC0F-5775-4727-8DD4-5325575BAC7B" id="BPMNEdge_sid-5E51BC0F-5775-4727-8DD4-5325575BAC7B"> <omgdi:waypoint x="336.5" y="178.0"></omgdi:waypoint> <omgdi:waypoint x="435.0" y="178.0"></omgdi:waypoint> </bpmndi:BPMNEdge> <bpmndi:BPMNEdge bpmnElement="sid-50EF2A93-83CE-44ED-AA41-F1A8F7ADE00C" id="BPMNEdge_sid-50EF2A93-83CE-44ED-AA41-F1A8F7ADE00C"> <omgdi:waypoint x="130.0" y="178.0"></omgdi:waypoint> <omgdi:waypoint x="236.5" y="178.0"></omgdi:waypoint> </bpmndi:BPMNEdge> </bpmndi:BPMNPlane> </bpmndi:BPMNDiagram></definitions>
基本概念介紹一個業務流程由以下幾個部分組成:
事件(Events)事件用來表明流程的生命週期中發生了什麼事。事件總是畫成一個圓圈, 在BPMN 2.0中事件有兩大分類:
捕獲(Catching)事件。當流程執行到該事件, 它會中斷執行,等待被觸發丟擲(Throwing))事件。當流程執行到該事件, 丟擲一個結果代表圖形如下:
閘道器(Gateways)Gateway是BPMN2規範中的流程定義元素,中文可稱為"閘道器"、"決策"、"判斷"。閘道器用來控制流程的執行流向,當在拆分路徑時產生令牌,在合併路徑時消費令牌。常用閘道器可分為排他閘道器(XOR)、並行閘道器(AND)和包容閘道器(OR),代表圖形如下:
活動(Activities)活動(Activities)是業務流程定義的核心元素,中文可稱為"活動"、"節點"、"步驟"。一個活動可以是流程中一個基本處理單元(如人工任務、服務任務),也可以是一個組合單元(如外部子流程、巢狀子流程),代表圖形如下:
依賴可能其他文章中還有一個依賴是activiti-spring-boot-starter-basic這兩個區別不太瞭解,但是兩個我都進行測試了,使用哪個都行。
這裡不加security會報錯,同時還要在啟動類的@SpringBootApplication註解上排除兩個類。
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <dependency> <groupId>org.activiti</groupId> <artifactId>activiti-spring-boot-starter</artifactId> <version>7.1.0.M6</version> </dependency> <dependency>
@SpringBootApplication(exclude = {SecurityAutoConfiguration.class, ManagementWebSecurityAutoConfiguration.class})public class SpringBootDemoApplication { public static void main(String[] args) { SpringApplication.run(SpringBootDemoApplication.class, args); }}
配置資料庫
由於資料還要儲存在資料庫中,還要在application.properties下配置資料庫資訊和activiti的資訊。
spring.datasource.url=jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8&autoReconnect=truespring.datasource.driver-class-name=com.mysql.jdbc.Driverspring.datasource.username=rootspring.datasource.password=hspring.activiti.database-schema-update=truespring.activiti.process-definition-location-prefix=classpath:/processes/spring.activiti.db-history-used=truespring.activiti.check-process-definitions=truespring.activiti.history-level=audit
啟動後會在資料庫中生成非常多個表
控制器package com.hxl.springbootdemo.activiti;import org.activiti.engine.RuntimeService;import org.activiti.engine.TaskService;import org.activiti.engine.runtime.ProcessInstance;import org.activiti.engine.task.Task;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RequestParam;import org.springframework.web.bind.annotation.RestController;import java.util.HashMap;import java.util.List;import java.util.Map;@RestControllerpublic class ActivitiController { @Autowired private TaskService taskService; @Autowired private RuntimeService runtimeService; /** * 啟動流程例項 * @param userName * @return */ @GetMapping("start") public String start(@RequestParam String userName){ Map<String, Object> map = new HashMap<>(); map.put("user", userName); ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("activiti-test", map); return "OK"; } /** * 獲取任務 * @param userName * @return */ @GetMapping("tasks") public String tasks(@RequestParam String userName){ List<Task> list = taskService.createTaskQuery().taskAssignee(userName).list(); return list.toString(); } /** * 完成任務 * @param id 任務id * @return */ @GetMapping("completetask") public String completeTask(@RequestParam String id) { taskService.complete(id); return "完成此任務"; }}
測試&結果http://localhost:8081/start?userName=小明 啟動流程OK
http://localhost:8081/tasks?userName=小明 獲取任務
[Task[id=b56be675-45b0-11eb-92b2-0242151ab6eb, name=寫作業]]
http://localhost:8081/completetask?id=b56be675-45b0-11eb-92b2-0242151ab6eb 完成任務
完成此任務
http://localhost:8081/tasks?userName=小明 重新獲取任務
[Task[id=cc3296b9-45b0-11eb-92b2-0242151ab6eb, name=打遊戲]]
請假流程設計
好了,最後再設計一個簡單的請假案例,先看一下圖,在這個圖中,第一步是使用者提交請假資訊,接著判斷請假時長,如果大於等於3天,則走院長審批,如果小於3天,則走班任審批,這裡用到了條件判斷,新增條件可以在UI介面上點選指向線後在flow condition一欄中新增,這裡就不說了。
<?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/processdef"> <process id="activiti-leave" name="activiti-leave" isExecutable="true"> <documentation>activiti-leave</documentation> <startEvent id="start" name="開始"></startEvent> <userTask id="user_task1" name="提交請假" activiti:assignee="#{user}"> <extensionElements> <activiti:formProperty id="new_property_1" name="userName" type="string"></activiti:formProperty> <activiti:formProperty id="new_property_2" name="day" type="long"></activiti:formProperty> <activiti:formProperty id="new_property_3" name="tel" type="string"></activiti:formProperty> <activiti:formProperty id="new_property_4" name="content" type="string"></activiti:formProperty> <modeler:initiator-can-complete xmlns:modeler="http://activiti.com/modeler"><![CDATA[false]]></modeler:initiator-can-complete> </extensionElements> </userTask> <sequenceFlow id="sid-055C2D31-C86C-4788-B373-D378575B98DC" sourceRef="start" targetRef="user_task1"></sequenceFlow> <userTask id="task_2" name="班主任稽核" activiti:assignee="banren"> <extensionElements> <modeler:initiator-can-complete xmlns:modeler="http://activiti.com/modeler"><![CDATA[false]]></modeler:initiator-can-complete> </extensionElements> </userTask> <exclusiveGateway id="sid-7230A3CF-B4DC-416F-AC22-21117F684115"></exclusiveGateway> <endEvent id="end" name="結束"></endEvent> <userTask id="task_3" name="院長" activiti:assignee="yuanzhang"> <extensionElements> <modeler:initiator-can-complete xmlns:modeler="http://activiti.com/modeler"><![CDATA[false]]></modeler:initiator-can-complete> </extensionElements> </userTask> <sequenceFlow id="sid-31E21674-09F8-4AB8-8672-CF08043EDD21" sourceRef="user_task1" targetRef="sid-7230A3CF-B4DC-416F-AC22-21117F684115"></sequenceFlow> <sequenceFlow id="sid-D7DD5340-DE9B-4436-8F94-748A8933AC81" sourceRef="task_3" targetRef="end"></sequenceFlow> <sequenceFlow id="sid-45E0E489-E181-4EEC-B162-DE7F6747F5DB" sourceRef="task_2" targetRef="end"></sequenceFlow> <sequenceFlow id="sid-DDE1F19E-DC48-4797-8CDA-22261EF293D3" sourceRef="sid-7230A3CF-B4DC-416F-AC22-21117F684115" targetRef="task_3"> <conditionExpression xsi:type="tFormalExpression"><![CDATA[${day>=3}]]></conditionExpression> </sequenceFlow> <sequenceFlow id="sid-D5171CDD-8C96-45F2-9E7B-34FF2683CEF0" sourceRef="sid-7230A3CF-B4DC-416F-AC22-21117F684115" targetRef="task_2"> <conditionExpression xsi:type="tFormalExpression"><![CDATA[${day<3}]]></conditionExpression> </sequenceFlow> </process> <bpmndi:BPMNDiagram id="BPMNDiagram_activiti-leave"> <bpmndi:BPMNPlane bpmnElement="activiti-leave" id="BPMNPlane_activiti-leave"> <bpmndi:BPMNShape bpmnElement="start" id="BPMNShape_start"> <omgdc:Bounds height="30.0" width="30.0" x="75.0" y="115.0"></omgdc:Bounds> </bpmndi:BPMNShape> <bpmndi:BPMNShape bpmnElement="user_task1" id="BPMNShape_user_task1"> <omgdc:Bounds height="80.0" width="100.0" x="171.5" y="90.0"></omgdc:Bounds> </bpmndi:BPMNShape> <bpmndi:BPMNShape bpmnElement="task_2" id="BPMNShape_task_2"> <omgdc:Bounds height="80.0" width="100.0" x="480.0" y="180.0"></omgdc:Bounds> </bpmndi:BPMNShape> <bpmndi:BPMNShape bpmnElement="sid-7230A3CF-B4DC-416F-AC22-21117F684115" id="BPMNShape_sid-7230A3CF-B4DC-416F-AC22-21117F684115"> <omgdc:Bounds height="40.0" width="40.0" x="345.0" y="110.0"></omgdc:Bounds> </bpmndi:BPMNShape> <bpmndi:BPMNShape bpmnElement="end" id="BPMNShape_end"> <omgdc:Bounds height="28.0" width="28.0" x="660.0" y="116.0"></omgdc:Bounds> </bpmndi:BPMNShape> <bpmndi:BPMNShape bpmnElement="task_3" id="BPMNShape_task_3"> <omgdc:Bounds height="80.0" width="100.0" x="480.0" y="15.0"></omgdc:Bounds> </bpmndi:BPMNShape> <bpmndi:BPMNEdge bpmnElement="sid-31E21674-09F8-4AB8-8672-CF08043EDD21" id="BPMNEdge_sid-31E21674-09F8-4AB8-8672-CF08043EDD21"> <omgdi:waypoint x="271.5" y="130.0"></omgdi:waypoint> <omgdi:waypoint x="345.0" y="130.0"></omgdi:waypoint> </bpmndi:BPMNEdge> <bpmndi:BPMNEdge bpmnElement="sid-45E0E489-E181-4EEC-B162-DE7F6747F5DB" id="BPMNEdge_sid-45E0E489-E181-4EEC-B162-DE7F6747F5DB"> <omgdi:waypoint x="580.0" y="188.75"></omgdi:waypoint> <omgdi:waypoint x="662.1280237439288" y="137.41998516004452"></omgdi:waypoint> </bpmndi:BPMNEdge> <bpmndi:BPMNEdge bpmnElement="sid-DDE1F19E-DC48-4797-8CDA-22261EF293D3" id="BPMNEdge_sid-DDE1F19E-DC48-4797-8CDA-22261EF293D3"> <omgdi:waypoint x="379.2083333333333" y="124.20833333333333"></omgdi:waypoint> <omgdi:waypoint x="480.0" y="77.9483282674772"></omgdi:waypoint> </bpmndi:BPMNEdge> <bpmndi:BPMNEdge bpmnElement="sid-055C2D31-C86C-4788-B373-D378575B98DC" id="BPMNEdge_sid-055C2D31-C86C-4788-B373-D378575B98DC"> <omgdi:waypoint x="105.0" y="130.0"></omgdi:waypoint> <omgdi:waypoint x="171.5" y="130.0"></omgdi:waypoint> </bpmndi:BPMNEdge> <bpmndi:BPMNEdge bpmnElement="sid-D5171CDD-8C96-45F2-9E7B-34FF2683CEF0" id="BPMNEdge_sid-D5171CDD-8C96-45F2-9E7B-34FF2683CEF0"> <omgdi:waypoint x="377.8051181102362" y="137.1948818897638"></omgdi:waypoint> <omgdi:waypoint x="480.0" y="192.7963525835866"></omgdi:waypoint> </bpmndi:BPMNEdge> <bpmndi:BPMNEdge bpmnElement="sid-D7DD5340-DE9B-4436-8F94-748A8933AC81" id="BPMNEdge_sid-D7DD5340-DE9B-4436-8F94-748A8933AC81"> <omgdi:waypoint x="580.0" y="81.04166666666667"></omgdi:waypoint> <omgdi:waypoint x="661.5832028216623" y="123.53291813628245"></omgdi:waypoint> </bpmndi:BPMNEdge> </bpmndi:BPMNPlane> </bpmndi:BPMNDiagram></definitions>
控制器package com.hxl.springbootdemo.activiti;import org.activiti.engine.HistoryService;import org.activiti.engine.RuntimeService;import org.activiti.engine.TaskService;import org.activiti.engine.history.HistoricTaskInstance;import org.activiti.engine.runtime.ProcessInstance;import org.activiti.engine.task.Task;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.PostMapping;import org.springframework.web.bind.annotation.RequestParam;import org.springframework.web.bind.annotation.RestController;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Map;@RestControllerpublic class ActivitiLeaveController { private Map<String,String> map =new HashMap<>(); @Autowired private TaskService taskService; @Autowired private RuntimeService runtimeService; @Autowired private HistoryService historyService; /** * 歷史任務 * @param userName * @return */ @GetMapping("history") private List<HistoricTaskInstance> history(@RequestParam String userName){ List<HistoricTaskInstance> list1 = historyService.createHistoricTaskInstanceQuery().taskAssignee(userName).list(); return list1; } /** * 完成任務 * @param id 任務id * @return */ @GetMapping("completetask") public String completeTask(@RequestParam String id) { taskService.complete(id); return "完成此任務"; } /** * 獲取任務 * @param userName * @return */ @GetMapping("tasks") public List<Map<String,Object>> tasks(@RequestParam String userName){ List<Map<String,Object>> result =new ArrayList<>(); List<Task> list = taskService.createTaskQuery().taskAssignee(userName).list(); for (Task task : list) { Map<String,Object> map =new HashMap<>(); ProcessInstance processInstance = runtimeService.createProcessInstanceQuery() .processInstanceId(task.getProcessInstanceId()) .singleResult(); Map<String, Object> variables = runtimeService.getVariables(processInstance.getId()); map.put("請假天數",variables.get("day")); map.put("請假人",variables.get("user")); map.put("手機號",variables.get("tel")); map.put("內容",variables.get("content")); map.put("taskInfo",task.toString()); result.add(map); } return result; } @PostMapping("leave") public String leave(@RequestParam String userName, @RequestParam int day, @RequestParam String tel, @RequestParam String content) { Map<String, Object> objectObjectHashMap = new HashMap<>(); objectObjectHashMap.put("user", userName); objectObjectHashMap.put("day", day); objectObjectHashMap.put("content",content); objectObjectHashMap.put("tel",tel); /** * 建立流程例項 */ ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("activiti-leave", objectObjectHashMap); runtimeService.setVariables(processInstance.getId(),objectObjectHashMap); Task task = taskService.createTaskQuery().processInstanceId(processInstance.getId()) .singleResult(); map.put(userName,processInstance.getId()); System.out.println(task); taskService.complete(task.getId(),objectObjectHashMap); return "提交成功id=" + task.getId(); }}
測試&結果1.http://localhost:8081/leave 提交資訊
這裡提交2個,一個小明請假1天,一個小張請假10天。
提交成功id=7ec509e1-45c8-11eb-8238-0242151ab6eb
2.http://localhost:8081/tasks?userName=banren 檢視班任任務
由於小明請1天假,所以由班主任稽核
[ { "手機號": "15048879423", "taskInfo": "Task[id=7ed42519-45c8-11eb-8238-0242151ab6eb, name=班主任稽核]", "請假人": "小明", "內容": "a", "請假天數": 1 }]
3.http://localhost:8081/completetask?id=7ed42519-45c8-11eb-8238-0242151ab6eb 班任完成審批
完成此任務
4.http://localhost:8081/tasks?userName=yuanzhang 檢視院長任務
[ { "手機號": "150xxxxxxxx", "taskInfo": "Task[id=f2cf9cd0-45c8-11eb-8238-0242151ab6eb, name=院長]", "請假人": "小張", "內容": "娶媳婦", "請假天數": 10 }]
5.http://localhost:8081/completetask?id=f2cf9cd0-45c8-11eb-8238-0242151ab6eb 院長完成審批
完成此任務
http://localhost:8081/history?userName=小明檢視歷史
[ { "id": "7ec509e1-45c8-11eb-8238-0242151ab6eb", "processInstanceId": "7ec298d9-45c8-11eb-8238-0242151ab6eb", "processDefinitionId": "activiti-leave:1:0d8b4a47-45c8-11eb-8238-0242151ab6eb", "startTime": "2020-12-24T09:14:58.755+00:00", "endTime": "2020-12-24T09:14:58.845+00:00", "durationInMillis": 90, "executionId": "7ec30e0e-45c8-11eb-8238-0242151ab6eb", "name": "提交請假", "assignee": "小明", "taskDefinitionKey": "user_task1", "priority": 50, "tenantId": "", "time": "2020-12-24T09:14:58.755+00:00", "createTime": "2020-12-24T09:14:58.755+00:00", "persistentState": { "taskDefinitionKey": "user_task1", "processDefinitionId": "activiti-leave:1:0d8b4a47-45c8-11eb-8238-0242151ab6eb", "durationInMillis": 90, "name": "提交請假", "assignee": "小明", "endTime": "2020-12-24T09:14:58.845+00:00", "priority": 50 }, "processVariables": {}, "taskLocalVariables": {}, "deleted": false, "inserted": false, "updated": false }]