Activiti工作流简单入门

BPMN 2.0

BPMN最初由业务流程倡议组织(BPMI)定案,现在BPMI并入到OMG(Object Management Group)了,则由OMG建立规范和维护。

BPMN 2.0正式更名为(Business Process Model And Notation)业务流程符号和模型,也有人继续称呼为业务流程建模标记法(Business Process Modeling Notaion),不过无所谓,不管是jBPM、Activiti还是国人开发的FixFlow,都遵循BPMN规范。

Maven配置

JBoss的开源框架都是比较庞大的,不过相对Activiti体积要小一点。下面为配置的依赖项。

1<!--Junit--> 2<dependency> 3 <groupId>junit</groupId> 4 <artifactId>junit</artifactId> 5 <version>${junit.version}</version> 6</dependency> 7 8<!--activiti--> 9<dependency> 10 <groupId>org.activiti</groupId> 11 <artifactId>activiti-engine</artifactId> 12 <version>${activiti.version}</version> 13</dependency> 14 15<dependency> 16 <groupId>org.activiti</groupId> 17 <artifactId>activiti-bpmn-layout</artifactId> 18 <version>${activiti.version}</version> 19</dependency> 20 21<dependency> 22 <groupId>org.activiti</groupId> 23 <artifactId>activiti-spring</artifactId> 24 <version>${activiti.version}</version> 25</dependency> 26 27<!--apache组件--> 28...

整合数据库

为什么要整合数据库?如果不整合数据库,我们大可以使用Quartz这些框架来做流程任务。实际上,Work Flow是用于一种长周期的几乎****异步的项目运行环境中,并且我们时刻需要将工作流程的状态记录下来,就是一种既注重结果,又注重过程的事务中,因此,整合数据库很有必要。

下面为配置源数据的XML文件,并且将databaseSchemaUpdate属性配置为drop-create,即在运行前删除原有的数据内容。

1<?xml version="1.0" encoding="UTF-8"?> 2<beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xsi:schemaLocation="http://www.springframework.org/schema/beans 5 http://www.springframework.org/schema/beans/spring-beans.xsd"> 6 7 <bean id="processEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration"> 8 <property name="databaseSchemaUpdate" value="drop-create"/> 9 <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/db_activiti?useUnicode=true&amp;characterEncoding=utf-8"/> 10 <property name="jdbcDriver" value="com.mysql.jdbc.Driver"/> 11 <property name="jdbcUsername" value="root"/> 12 <property name="jdbcPassword" value="****"/> 13 <property name="jobExecutorActivate" value="true"/> 14 </bean> 15</beans>

默认配置文件名为activiti.cfg.xml,可以在源文件中找到。

另外,如果有必要,请将MySQL设置为区分大小写,即lower_case_table_names = 0。

数据内容会在运行前自动创建,详细表结构内容可参考官网完整信息。

创建工作流文件

由于BPMN规范的作用,一些高级的IDE会自动识别后缀为*.bpmn的文件,不过这些都无所谓,bpmn文件实际上就是XML文件,只是加上了一些图形的标记,如width、height、x和y的坐标,下面为一个招聘面试流程,只包含流程节点,不包含位置标记节点。

1<?xml version="1.0" encoding="UTF-8"?> 2<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" 3 xmlns:activiti="http://activiti.org/bpmn" 4 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 5 targetNamespace="Examples" 6 xsi:schemaLocation="http://www.omg.org/spec/BPMN/20100524/MODEL 7 http://www.omg.org/spec/BPMN/2.0/20100501/BPMN20.xsd"> 8 <process id="Interview" name="某公司2012年实习生招聘流程"> 9 <documentation>招聘工作流程</documentation> 10 <startEvent id="start" name="实习生招聘启动"/> 11 <userTask id="bishi" name="笔试" activiti:candidateGroups="人力资源部"/> 12 <sequenceFlow id="flow1" name="" sourceRef="start" targetRef="bishi"/> 13 <userTask id="yimian" name="技术一面" activiti:candidateGroups="技术部"/> 14 <sequenceFlow id="flow2" name="" sourceRef="bishi" targetRef="yimian"/> 15 <userTask id="ermian" name="技术二面" activiti:candidateGroups="技术部"/> 16 <sequenceFlow id="flow3" name="" sourceRef="yimian" targetRef="ermian"/> 17 <userTask id="hrmian" name="HR面" activiti:candidateGroups="人力资源部"/> 18 <sequenceFlow id="flow4" name="" sourceRef="ermian" targetRef="hrmian"/> 19 <userTask id="luyong" name="录用,发放Offer" activiti:candidateGroups="人力资源部"/> 20 <sequenceFlow id="flow5" name="" sourceRef="hrmian" targetRef="luyong"/> 21 <endEvent id="end" name="实习生招聘结束"/> 22 <sequenceFlow id="flow6" name="" sourceRef="luyong" targetRef="end"/> 23 </process> 24 25</definitions>

为了便于阅读,一些高级IDE可以转化为图形符号,如下图:

测试运行

有了流程引擎的配置文件和流程文件后,就可以编写代码启动流程引擎并加载该流程文件了。测试清单如下:

1@Test 2public void processTests(){ 3 // 加载配置文件 4 ProcessEngine processEngine = ProcessEngineConfiguration.createProcessEngineConfigurationFromResource("activiti.cfg.xml").buildProcessEngine(); 5 RepositoryService repositoryService = processEngine.getRepositoryService(); 6 RuntimeService runtimeService = processEngine.getRuntimeService(); 7 repositoryService.createDeployment().addClasspathResource("Interview.bpmn").deploy(); 8 String processId = runtimeService.startProcessInstanceByKey("Interview").getId(); 9 10 TaskService taskService = processEngine.getTaskService(); 11 //得到笔试的流程 12 System.out.println("\n***************笔试流程开始***************"); 13 14 List<Task> tasks = taskService.createTaskQuery().taskCandidateGroup("人力资源部").list(); 15 for (Task task : tasks) { 16 System.out.println("人力资源部的任务:name:"+task.getName()+",id:"+task.getId()); 17 taskService.claim(task.getId(), "张三"); 18 } 19 20 System.out.println("张三的任务数量:"+taskService.createTaskQuery().taskAssignee("张三").count()); 21 tasks = taskService.createTaskQuery().taskAssignee("张三").list(); 22 for (Task task : tasks) { 23 System.out.println("张三的任务:name:"+task.getName()+",id:"+task.getId()); 24 taskService.complete(task.getId()); 25 } 26 27 System.out.println("张三的任务数量:"+taskService.createTaskQuery().taskAssignee("张三").count()); 28 System.out.println("***************笔试流程结束***************"); 29 30 System.out.println("\n***************一面流程开始***************"); 31 tasks = taskService.createTaskQuery().taskCandidateGroup("技术部").list(); 32 for (Task task : tasks) { 33 System.out.println("技术部的任务:name:"+task.getName()+",id:"+task.getId()); 34 taskService.claim(task.getId(), "李四"); 35 } 36 37 System.out.println("李四的任务数量:"+taskService.createTaskQuery().taskAssignee("李四").count()); 38 for (Task task : tasks) { 39 System.out.println("李四的任务:name:"+task.getName()+",id:"+task.getId()); 40 taskService.complete(task.getId()); 41 } 42 43 System.out.println("李四的任务数量:"+taskService.createTaskQuery().taskAssignee("李四").count()); 44 System.out.println("***************一面流程结束***************"); 45 46 System.out.println("\n***************二面流程开始***************"); 47 tasks = taskService.createTaskQuery().taskCandidateGroup("技术部").list(); 48 for (Task task : tasks) { 49 System.out.println("技术部的任务:name:"+task.getName()+",id:"+task.getId()); 50 taskService.claim(task.getId(), "李四"); 51 } 52 53 System.out.println("李四的任务数量:"+taskService.createTaskQuery().taskAssignee("李四").count()); 54 for (Task task : tasks) { 55 System.out.println("李四的任务:name:"+task.getName()+",id:"+task.getId()); 56 taskService.complete(task.getId()); 57 } 58 59 System.out.println("李四的任务数量:"+taskService.createTaskQuery().taskAssignee("李四").count()); 60 System.out.println("***************二面流程结束***************"); 61 62 System.out.println("***************HR面流程开始***************"); 63 tasks = taskService.createTaskQuery().taskCandidateGroup("人力资源部").list(); 64 for (Task task : tasks) { 65 System.out.println("技术部的任务:name:"+task.getName()+",id:"+task.getId()); 66 taskService.claim(task.getId(), "李四"); 67 } 68 69 System.out.println("李四的任务数量:"+taskService.createTaskQuery().taskAssignee("李四").count()); 70 for (Task task : tasks) { 71 System.out.println("李四的任务:name:"+task.getName()+",id:"+task.getId()); 72 taskService.complete(task.getId()); 73 } 74 75 System.out.println("李四的任务数量:"+taskService.createTaskQuery().taskAssignee("李四").count()); 76 System.out.println("***************HR面流程结束***************"); 77 78 System.out.println("\n***************录用流程开始***************"); 79 tasks = taskService.createTaskQuery().taskCandidateGroup("人力资源部").list(); 80 for (Task task : tasks) { 81 System.out.println("技术部的任务:name:"+task.getName()+",id:"+task.getId()); 82 taskService.claim(task.getId(), "李四"); 83 } 84 85 System.out.println("李四的任务数量:"+taskService.createTaskQuery().taskAssignee("李四").count()); 86 for (Task task : tasks) { 87 System.out.println("李四的任务:name:"+task.getName()+",id:"+task.getId()); 88 taskService.complete(task.getId()); 89 } 90 91 System.out.println("李四的任务数量:"+taskService.createTaskQuery().taskAssignee("李四").count()); 92 System.out.println("***************录用流程结束***************"); 93 94 HistoryService historyService = processEngine.getHistoryService(); 95 HistoricProcessInstance historicProcessInstance = historyService 96 .createHistoricProcessInstanceQuery() 97 .processInstanceId(processId).singleResult(); 98 System.out.println("\n流程结束时间:"+historicProcessInstance.getEndTime()); 99}

代码清单中使用 ProcessEngines类加载默认的流程配置文件(activiti.cfg.xml),再获取各个服务组件的实例。 RepositoryService主要用于管理流程的资源, RuntimeService主要用于流程运行时的流程管理,TaskService主要用于管理流程任务。最后, HistoricProcessInstance会将工作的流程历史记录下来。

点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

MySQL部分从库上面因为大量的临时表tmp_table造成慢查询

背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_

皕杰报表之UUID

​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为

2020年前端实用代码段,为你的工作保驾护航

有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )

KVM调整cpu和内存

一.修改kvm虚拟机的配置1、virsheditcentos7找到“memory”和“vcpu”标签,将<namecentos7</name<uuid2220a6d1a36a4fbb8523e078b3dfe795</uuid