序言:近期业务涉及到各种奇葩的中国式审批,用activiti工作流来实现,网上教程坑太多,故写此文章总结备忘...
一、前期准备
1.maven依赖
<activiti.version>5.21.0</activiti.version>
<!-- Activiti --> <dependency> <groupId>org.activiti</groupId> <artifactId>activiti-engine</artifactId> <version>${activiti.version}</version> </dependency> <dependency> <groupId>org.activiti</groupId> <artifactId>activiti-spring</artifactId> <version>${activiti.version}</version> </dependency> <dependency> <groupId>org.activiti</groupId> <artifactId>activiti-explorer</artifactId> <version>${activiti.version}</version> <exclusions> <exclusion> <artifactId>vaadin</artifactId> <groupId>com.vaadin</groupId> </exclusion> <exclusion> <artifactId>dcharts-widget</artifactId> <groupId>org.vaadin.addons</groupId> </exclusion> <exclusion> <artifactId>activiti-simple-workflow</artifactId> <groupId>org.activiti</groupId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.activiti</groupId> <artifactId>activiti-modeler</artifactId> <version>${activiti.version}</version> </dependency> <dependency> <groupId>org.activiti</groupId> <artifactId>activiti-diagram-rest</artifactId> <version>${activiti.version}</version> </dependency>
二、定义流程
1.使用 activiti-modeler 绘制流程图(此插件集成方式请自行百度)
2.部署流程
有多种方式(classpath、InputStream、字符串)部署,这里使用InputStream方式。
/**流程引擎(核心对象),默认加载类路径下命名为activiti.cfg.xml*/ ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine(); public void deployementProcessDefinitionByInputStream() throws FileNotFoundException { //获取资源相对路径 String bpmnPath = "diagrams/helloworld.bpmn"; String pngPath = "diagrams/helloworld.png"; //读取资源作为一个输入流 FileInputStream bpmnfileInputStream = new FileInputStream(bpmnPath); FileInputStream pngfileInputStream = new FileInputStream(pngPath); Deployment deployment = processEngine.getRepositoryService()//获取流程定义和部署对象相关的Service .createDeployment()//创建部署对象 .addInputStream("helloworld.bpmn",bpmnfileInputStream) .addInputStream("helloworld.png", pngfileInputStream) .deploy();//完成部署 System.out.println("部署ID:"+deployment.getId()); System.out.println("部署时间:"+deployment.getDeploymentTime()); }
3.使用流程
3.1 启动流程
/** * 启动流程 * * @param procDefKey 流程定义KEY * @param businessTable 业务表表名 * @param businessId 业务表编号 * @param title 流程标题,显示在待办任务标题 * @param vars 流程变量 * @return 流程实例ID */ public String startProcess(String procDefKey, String businessTable, String businessId, String title, Map<String, Object> vars) { String userId = UserUtils.getUser().getId(); // 用来设置启动流程的人员ID,引擎会自动把用户ID保存到activiti:initiator中 identityService.setAuthenticatedUserId(userId); // 设置流程变量 if (vars == null) { vars = Maps.newHashMap(); } // 设置流程标题 if (StringUtils.isNotBlank(title)) { vars.put("title", title); } // 启动流程 ProcessInstance procIns = runtimeService.startProcessInstanceByKey(procDefKey, businessTable + ":" + businessId, vars); // 更新业务表流程实例ID Act act = new Act(); act.setBusinessTable(businessTable);// 业务表名 act.setBusinessId(businessId); // 业务表ID act.setProcInsId(procIns.getId()); actDao.updateProcInsIdByBusinessId(act); return act.getProcInsId(); }
//启动流程后,将流程实例id (procInsId) 保存到业务表中
//dao层 <update id="updateProcInsIdByBusinessId"> UPDATE ${businessTable} SET proc_ins_id = #{procInsId} WHERE id = #{businessId} </update>
3.2 流程变量
Map<String, Object> vars = Maps.newHashMap(); vars.put("pass", 1);//是否通过 ...各种参数... 此处省略
3.3 流程是否结束
/** * 判断流程是否结束 * * @param processInstanceId * @return */ public boolean isEnd(String processInstanceId) { ProcessInstance pi = runtimeService.createProcessInstanceQuery()// .processInstanceId(processInstanceId)//使用流程实例ID查询 .singleResult(); if (pi == null) { return true; } else { return false; } }
3.4 撤回流程(删除流程实例&#