Activiti是由Alfresco發佈的業務流程管理(BPM)框架,它是覆蓋了業務流程管理、工作流、服務協作等領域的一個開源的、靈活的、易擴展的可執行流程語言框架。Activiti基於Apache許可的開源BPM平臺,創始人Tom Baeyens是JBoss jBPM的項目架構師,它特色是提供了eclipse插件,開發人員可以通過插件直接繪畫出業務流程圖。bliblibli...
概念啥的就不扯了,網上大把資料.話不多說,直接切入正題,預完成一個員工請假流程,1天部門經理審核,3天以內(含3天)副總審核,3天到7天(含7天)總經理審核,7天以上其他渠道審核.
- demo結構圖如上圖所示,springboot+maven項目,整合Activiti6.0,pom依賴如下圖所示:
org.springframework.boot spring-boot-starter-parent 2.1.5.RELEASE cn.dale activiti-demo 1.0-SNAPSHOT 1.8 UTF-8 org.springframework.boot spring-boot-starter-jdbc org.mybatis.spring.boot mybatis-spring-boot-starter 2.0.1 org.springframework.boot spring-boot-starter-web mysql mysql-connector-java runtime org.springframework.boot spring-boot-starter-test test com.alibaba druid 1.1.10 org.activiti activiti-spring-boot-starter-basic 6.0.0 org.slf4j slf4j-api 1.7.21 org.slf4j slf4j-log4j12 1.7.21 org.springframework.boot spring-boot-maven-plugin
Activiti6.0已經整合到springboot了,所以上手起來順暢的多.
- 在application.properties文件中做些許配置:
##spring database configuration spring.datasource.url=jdbc:mysql://172.10.3.150:3306/activiti?useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull spring.datasource.username=root spring.datasource.password=Mysql_108 spring.datasource.driver-class-name=com.mysql.jdbc.Driver #activiti #自動檢查、部署流程定義文件 spring.activiti.check-process-definitions=true #自動更新數據庫結構 spring.activiti.database-schema-update=true #流程定義文件存放目錄 spring.activiti.process-definition-location-prefix=classpath:/processes/
- 接下來運行一段代碼,生成工作流所需的表,你得先在數據庫裡建好數據庫activiti:
package cn.dale.activitidemo; import org.activiti.engine.ProcessEngine; import org.activiti.engine.ProcessEngineConfiguration; import org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration; /** * @Author: dale * @Date: 2019/11/5 17:26 */ public class ActivitiTable { public static void main(String[] args) { // 引擎配置 ProcessEngineConfiguration cfg = new StandaloneProcessEngineConfiguration() .setJdbcUrl("jdbc:mysql://172.10.3.150:3306/activiti?useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull") .setJdbcUsername("root") .setJdbcPassword("Mysql_108") .setJdbcDriver("com.mysql.jdbc.Driver") .setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE); // 獲取流程引擎對象 ProcessEngine processEngine = cfg.buildProcessEngine(); } }
- run main()方法,表就建好了,接下來在idea添加一個叫actiBPM的插件,直接下載安裝就好了,重啟idea;
- 在resources目錄下新建process目錄,右鍵新建bpmn文件—>leave_process.bpmn,通過拖拽右邊的圖形元素繪圖,將鼠標停留在元素中部,出現黑點後可以畫連線.
- 畫圖時要注意id不能重複,Name要想好怎麼命名,一個項目會有很多圖形元素需要命名,一定要起名有規律,後面要用到的.哪個紅色中間帶個×的叫排他網關,達到某種條件才能進入這個網關,需要人為設定,如下圖所示:
這個也不好描述,直接上這個圖對應的xml文件:
7}]]>
要用的使用,把後綴名改成bpmn就行了.
- 跑一個測試用例,看能不能按照預先設定的邏輯執行:
package cn.dale.activitidemo; import cn.dale.activitidemo.entity.Employee; import cn.dale.activitidemo.task.ActivitiTask; import org.activiti.engine.*; import org.activiti.engine.impl.persistence.entity.ExecutionEntity; import org.activiti.engine.runtime.ProcessInstance; import org.activiti.engine.task.Task; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.annotation.Rollback; import org.springframework.test.context.junit4.SpringRunner; import org.springframework.test.context.web.WebAppConfiguration; import org.springframework.transaction.annotation.Transactional; import java.util.HashMap; import java.util.List; import java.util.Map; /** * @Author: dale * @Date: 2019/11/5 17:59 */ @RunWith(SpringRunner.class) @WebAppConfiguration @SpringBootTest @Transactional @Rollback(false) //@Ignore public class ActiTest { @Autowired private RuntimeService runtimeService; @Autowired private IdentityService identityService; @Autowired private TaskService taskService; @Autowired private RepositoryService repositoryService; //初始化一個要請假的員工 private static final Employee emp = new Employee("zs", 8); @Test public void testInitProcess() { System.out.println("method startActivityDemo begin...."); System.out.println("調用流程存儲服務,已部署流程數量:" + repositoryService.createDeploymentQuery().count()); Map map = new HashMap(); // 流程圖裡寫的${user} ,這裡傳進去user map.put("Applier", emp.getEmployeeName()); map.put("DeptMng", "ls"); map.put("ViceMng", "ww"); map.put("GnlMng", "zl"); map.put("special", "sq"); // 指定流程的發起者 不指定發起者的字段就為空,注意跟審核人分開 identityService.setAuthenticatedUserId(emp.getEmployeeName()); //流程啟動 ExecutionEntity pi = (ExecutionEntity) runtimeService.startProcessInstanceByKey("start", map); String processInstanceId = pi.getId(); System.out.println("流程開啟成功,流程實例id:" + processInstanceId); ActivitiTask at = new ActivitiTask(taskService); //開始進行流程 while (runtimeService .createProcessInstanceQuery()//獲取查詢對象 .processInstanceId(processInstanceId)//根據id查詢流程實例 .singleResult()//獲取查詢結果,如果為空,說明這個流程已經執行完畢,否則,獲取任務並執行 != null) { Task task = taskService.createTaskQuery()//創建查詢對象 .processInstanceId(processInstanceId)//通過流程實例id來查詢當前任務 .singleResult();//獲取單個查詢結果 String taskName = task.getName(); System.out.println("任務ID: " + task.getId()); System.out.println("任務的辦理人: " + task.getAssignee()); System.out.println("任務名稱: " + taskName); System.out.println("任務的創建時間: " + task.getCreateTime()); System.out.println("流程實例ID: " + task.getProcessInstanceId()); switch (taskName) { case "Applier": //職員節點 at.completeEmployeeTask(task, emp); break; case "DeptMng": //部門經理節點 at.completeLeaderTask(task, emp); break; default: //經理節點 at.completeJingliTask(task, emp); break; } System.out.println(emp.getApplyStatus().getName()); } System.out.println("method startActivityDemo end...."); } }
ActivitiTask代碼:
package cn.dale.activitidemo.task; import cn.dale.activitidemo.entity.Employee; import cn.dale.activitidemo.enums.ApplyStatusEnum; import org.activiti.engine.TaskService; import org.activiti.engine.task.Task; import java.util.HashMap; import java.util.Map; /** * @Author: dale * @Date: 2019/11/6 15:38 */ public class ActivitiTask { private TaskService taskService; public ActivitiTask(TaskService taskService) { this.taskService = taskService; } //職員提交申請 public void completeEmployeeTask(Task task, Employee emp){ //獲取任務id String taskId = task.getId(); //完成任務 taskService.complete(taskId); emp.setApplyStatus(ApplyStatusEnum.AUDITING); System.out.println("職員已經提交申請......."); } //領導審批 public void completeLeaderTask(Task task, Employee emp){ //獲取任務id String taskId = task.getId(); //領導意見 Map variables = new HashMap(); variables.put("day",emp.getDay()); variables.put("deptMngResult", 1); emp.setApplyStatus(ApplyStatusEnum.AUDITING); //完成任務 taskService.complete(taskId, variables); System.out.println("領導審核完畢........"); } //經理審批 public void completeJingliTask(Task task, Employee emp){ //獲取任務id String taskId = task.getId(); String name = task.getName(); //經理意見 Map variables = new HashMap(); variables.put("day",emp.getDay()); // variables.put("result", 0); // emp.setApplyStatus(ApplyStatusEnum.NO); variables.put("result", 1); emp.setApplyStatus(ApplyStatusEnum.YES); //完成任務 taskService.complete(taskId, variables); System.out.println("經理審核完畢........,審核經理:"+name); } }
請假被sq拒絕後的運行結果:
可以看到流程一直循環執行,因為到最後一環被拒絕了,現在我讓sq同意請假申請,結果如下圖:
這樣,一個8天的請假流程就順利走完了.簡單的一個案例,當然Activiti還有滿足不同場景需求的更多的Api,這裡就不一一列舉,大家根據自己項目的實際需要去學習
演示案例GitHub倉庫地址:https://github.com/DaleZl/ActivitiDemo.git
關鍵字: 業務流程 artifactId parent