官网:https://camunda.com/
官方文档:https://docs.camunda.org/get-started/spring-boot/project-setup/
阅读新体验:http://www.zhouhong.icu/post/155
一、简介
Camunda是一个工作流引擎,执行Bpmn2.0标准,因此依赖于基于bpmn的流程图(本质上是一个xml文件)
二、一个完整的报销 demo 入门
1、创建一个SpringBoot项目,导入数据库依赖、Camunda 等依赖
1 <dependency> 2 <groupId>org.springframework.boot</groupId> 3 <artifactId>spring-boot-starter-web</artifactId> 4 </dependency> 5 <dependency> 6 <groupId>org.mybatis.spring.boot</groupId> 7 <artifactId>mybatis-spring-boot-starter</artifactId> 8 <version>2.2.0</version> 9 </dependency> 10 11 <!-- https://mvnrepository.com/artifact/org.camunda.bpm.springboot/camunda-bpm-spring-boot-starter-webapp --> 12 <dependency> 13 <groupId>org.camunda.bpm.springboot</groupId> 14 <artifactId>camunda-bpm-spring-boot-starter-webapp</artifactId> 15 <version>3.4.4</version> 16 </dependency> 17 <!-- https://mvnrepository.com/artifact/org.camunda.bpm.springboot/camunda-bpm-spring-boot-starter-rest --> 18 <dependency> 19 <groupId>org.camunda.bpm.springboot</groupId> 20 <artifactId>camunda-bpm-spring-boot-starter-rest</artifactId> 21 <version>3.4.4</version> 22 </dependency> 23 24 <dependency> 25 <groupId>mysql</groupId> 26 <artifactId>mysql-connector-java</artifactId> 27 <scope>runtime</scope> 28 </dependency> 29 <dependency> 30 <groupId>org.projectlombok</groupId> 31 <artifactId>lombok</artifactId> 32 <optional>true</optional> 33 </dependency> 34 <dependency> 35 <groupId>org.springframework.boot</groupId> 36 <artifactId>spring-boot-starter-test</artifactId> 37 <scope>test</scope> 38 </dependency> 39 <dependency> 40 <groupId>junit</groupId> 41 <artifactId>junit</artifactId> 42 <version>4.13.2</version> 43 </dependency> 44 <dependency> 45 <groupId>com.aliyun</groupId> 46 <artifactId>aliyun-java-sdk-ecs</artifactId> 47 <version>4.17.6</version> 48 </dependency>
application.yml 部分配置:
1 spring: 2 application: 3 name: camunda-demo 4 #数据源配置 5 datasource: 6 url: jdbc:mysql://127.0.0.1:3306/camunda-demo?serverTimezone=Asia/Shanghai 7 driver-class-name: com.mysql.cj.jdbc.Driver 8 username: root 9 password: 123456 10 camunda: 11 bpm: 12 #配置账户密码来访问Camunda自带的管理界面 13 admin-user: 14 id: admin 15 password: admin 16 first-name: admin 17 filter: 18 create: All tasks 19 #禁止自动部署resources下面的bpmn文件 20 auto-deployment-enabled: false
2、启动后会生成47张表:
3、访问 http://localhost:8080/
4、下载bpmn建模工具:https://camunda.com/download/modeler/
5、画一个报销流程图,申请人为shangsan、人事为lisi、经理为wangwu,保存后放到项目resources目录下面,同时进入控制台Admin目录下建立相关的人员信息。
注意:报销金额判断条件使用 Expression 表达式
6、流程定义部署
@PostMapping("/deploy") public void deploy() { Deployment deploy = repositoryService.createDeployment() .addClasspathResource("BPMN/apply.bpmn") .deploy(); System.out.println(deploy.getId()); }
用PostMan发起流程后会在ACT_RE_DEPLOYMENT表中看到一个流程的实例
7、启动流程实例
@PostMapping("/start") public void runProcinst(){ Map<String,Object> params = new HashMap<>(); params.put("money",2001); ProcessInstance holiday = runtimeService.startProcessInstanceByKey("apply",params); }
然后切换到zhangsan用户,在控制台TaskList下查看
8、审批通过,在审批的过程中可以随意添加审批信息
@PostMapping("/taskComplete") public void taskComplete(){ Task task = taskService.createTaskQuery() .taskAssignee("zhangsan") .singleResult(); params.put("approve2","lisi"); Map<String,Object> params = new HashMap<>(); taskService.complete(task.getId(),params); }
切换 lisi 用户在控制台查看任务
9、进入控制台在Cockplt中查看流程走到哪(因为我们的money设置的是2001,大于2000,所以流程走到下面的那个分支)
10、其他关于流程的一些简单操作
1 /** 2 * @ClassName: camunda-demo 3 * @Description: 4 * @Author: zhouhong 5 * @Create: 2021-07-08 10:06 6 **/ 7 8 @RestController 9 public class Test { 10 11 @Autowired 12 RepositoryService repositoryService; 13 @Autowired 14 RuntimeService runtimeService; 15 @Autowired 16 TaskService taskService; 17 @Autowired 18 HistoryService historyService; 19 @Autowired 20 ProcessEngine processEngine; 21 22 @Autowired 23 ProcessEngine engine; 24 25 /** 26 * @Description: 流程定义部署 27 * @Author: zhouhong 28 * @Date: 2021/7/8 29 */ 30 @PostMapping("/deploy") 31 public void deploy() { 32 Deployment deploy = repositoryService.createDeployment() 33 .addClasspathResource("BPMN/apply.bpmn") 34 .deploy(); 35 System.out.println(deploy.getId()); 36 } 37 38 /** 39 * @Description: 开启一个流程实例 40 * @Author: zhouhong 41 * @Date: 2021/7/8 42 */ 43 @PostMapping("/start") 44 public void runProcinst(){ 45 Map<String,Object> params = new HashMap<>(); 46 params.put("money",2001); 47 ProcessInstance apply = runtimeService.startProcessInstanceByKey("apply",params); 48 System.out.println(apply.getProcessDefinitionId()); 49 System.out.println(apply.getId()); 50 System.out.println(apply.getProcessInstanceId()); 51 } 52 53 /** 54 * @Description: 流程任务查询 55 * @Author: zhouhong 56 * @Date: 2021/7/8 57 */ 58 @PostMapping("/taskquery") 59 public void taskQuery() { 60 List<Task> tasks = taskService.createTaskQuery() 61 .processDefinitionKey("apply") 62 .list(); 63 for (Task task : tasks) { 64 System.out.println(task.getAssignee()); 65 System.out.println(task.getId()); 66 System.out.println(task.getName()); 67 System.out.println(task.getTenantId()); 68 } 69 } 70 71 /** 72 * @Description: 当前需要处理的任务 73 * @Author: zhouhong 74 * @Date: 2021/7/8 75 */ 76 @PostMapping("/mytaskquery") 77 public List<HistoricTaskInstance> myTaskQuery() { 78 List<HistoricTaskInstance> instances = engine.getHistoryService().createHistoricTaskInstanceQuery() 79 .taskAssignee("lisi").unfinished().orderByHistoricActivityInstanceStartTime().asc().list(); 80 return instances; 81 } 82 83 /** 84 * @Description: 流程任务执行 85 * @Author: zhouhong 86 * @Date: 2021/7/8 87 */ 88 @PostMapping("/taskComplete") 89 public void taskComplete(){ 90 //目前lisi只有一个任务,业务中根据场景选择其他合适的方式 91 Task task = taskService.createTaskQuery() 92 .taskAssignee("zhangsan") 93 .singleResult(); 94 Map<String,Object> params = new HashMap<>(); 95 params.put("approve2","lisi"); 96 taskService.complete(task.getId(),params); 97 } 98 99 /** 100 * @Description: 流程定义查询 101 * @Author: zhouhong 102 * @Date: 2021/7/8 103 */ 104 @PostMapping("/queryDefine") 105 public void queryDefine(){ 106 ProcessDefinitionQuery query = repositoryService.createProcessDefinitionQuery(); 107 List<ProcessDefinition> definitions = query.processDefinitionKey("apply") 108 .orderByProcessDefinitionVersion() 109 .desc() 110 .list(); 111 for (ProcessDefinition definition : definitions) { 112 System.out.println(definition.getDeploymentId()); 113 System.out.println(definition.getName()); 114 System.out.println(definition.getVersion()); 115 System.out.println(definition.getId()); 116 System.out.println(definition.getKey()); 117 } 118 } 119 120 /** 121 * 删除流程定义 122 */ 123 @PostMapping("/deleteDefine") 124 public void deleteDefine(){ 125 ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery(); 126 List<ProcessDefinition> definitions = processDefinitionQuery.processDefinitionKey("apply") 127 .orderByProcessDefinitionVersion() 128 .asc() 129 .list(); 130 ProcessDefinition processDefinition = definitions.get(0); 131 if (processDefinition != null){ 132 repositoryService.deleteDeployment(processDefinition.getDeploymentId(),true); 133 } 134 } 135 136 /** 137 * 查询历史信息 138 */ 139 @PostMapping("/queryHistory") 140 public void queryHistory(){ 141 List<HistoricActivityInstance> list = historyService.createHistoricActivityInstanceQuery() 142 .finished() 143 .orderByHistoricActivityInstanceEndTime() 144 .asc() 145 .list(); 146 for (HistoricActivityInstance instance : list) { 147 System.out.println(instance.getActivityId()); 148 System.out.println(instance.getProcessDefinitionKey()); 149 System.out.println(instance.getAssignee()); 150 System.out.println(instance.getStartTime()); 151 System.out.println(instance.getEndTime()); 152 System.out.println("============================="); 153 } 154 } 155 156 /** 157 * 启动一个流程实例,并且添加一个业务key 158 * 业务key 可以在 act_ru_execution 中看到 159 */ 160 161 public void startProcInstAddBusinessKey(){ 162 ProcessInstance apply = runtimeService.startProcessInstanceByKey("apply", "aaaa-scsc-89uc"); 163 System.out.println(apply.getBusinessKey()); 164 } 165 166 } 167