Activiti7工作流引擎:基础篇 Hello World
Posted vbirdbest
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Activiti7工作流引擎:基础篇 Hello World相关的知识,希望对你有一定的参考价值。
越是有用的东西越不值钱,你比方说粮食、水、蔬菜,能够满足我们生存的东西一点都不值钱;
而那些对我们生活不起任何作用的东西特别值钱,你比方说砖石、包包、古董、字画;
所以说你要想挣大钱你就得整那些没有用的。
一:工作流的开发步骤
定义流程
:使用IDEA插件actiBPM定义流程文件.bpmn
。部署流程
:将.bpmn文件保存到数据库中。启动流程
:启动工作流中的第一个任务节点,即提出申请。办理流程
:审批当前任务流程,完成最后一个任务就算结束工作流。
二:示例一:负责人固定
2.1 定义流程
-
Id:最好不要使用默认的数字而是起个更加直观的名字,因为程序中可能要根据Id值来查询任务,如果使用数字作为查询条件会非常不直观。
-
Assignee: 表示任务负责人、办理人。
生成.png文件
将helloworld.bpmn文件重名为helloworld.xml
文件,右键 --> Diagrams --> Show BPMN 2.0 Designer --> Export to Image File ,然后将helloworld.png放入到项目resources/bpmn/目录下, 并把xml后缀改为原来的bpmn后缀。
为什么要导出成图片呢?可以将图片放在Web系统中供其他人员了解流程审批步骤。
2.2 部署流程、启动流程、办理流程
public class HelloWorldTest
/**
* 创建数据库表
*/
@Test
public void testCreateDBTable()
ProcessEngines.getDefaultProcessEngine();
/**
* 部署流程:将.bpmn文件保存到数据库中,.bpmn属于资源部署所以使用RepositoryService。
*/
@Test
public void delopyBpmn()
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
Deployment deploy = processEngine.getRepositoryService()
.createDeployment()
.addClasspathResource("bpmn/helloworld.bpmn")
// 图片不是必须的,不影响审批流程
.addClasspathResource("bpmn/helloworld.png")
.name("请假流程")
.deploy();
// DeploymentEntity[id=1, name=请假流程]
System.out.println(deploy);
/**
* 启动流程实例:发起申请请求
*/
@Test
public void startProcessInstance()
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
ProcessInstance processInstance = processEngine.getRuntimeService()
.startProcessInstanceByKey("helloworld");
System.out.println(processInstance.getId());
System.out.println(processInstance.getProcessInstanceId());
System.out.println(processInstance.getProcessDefinitionId());
/**
* 办理(完成)任务:zhangsan审核自己通过,并将审批交给下个流程审核
*/
@Test
public void completeTask()
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
TaskService taskService = processEngine.getTaskService();
Task task = taskService
.createTaskQuery()
.processDefinitionKey("helloworld")
.taskAssignee("zhangsan")
.singleResult();
// 完成之前可以先添加一些历史意见
JSONObject jsonObject = new JSONObject();
jsonObject.put("userId", "1");
jsonObject.put("suggestion", "同意");
taskService.addComment(task.getId(), task.getProcessInstanceId(), "MyCustomComment", JSONObject.toJSONString(jsonObject));
// 办理完成任务
taskService.complete(task.getId());
/**
* 办理(完成)任务:项目经理完成审批,并将任务交给下个负责人审批
*/
@Test
public void completeTaskPM()
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
TaskService taskService = processEngine.getTaskService();
Task task = taskService
.createTaskQuery()
.processDefinitionKey("helloworld")
.taskAssignee("pm")
.singleResult();
taskService.complete(task.getId());
/**
* 办理(完成)任务:人事审批通过,整个流程结束
*/
@Test
public void completeTaskHR()
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
TaskService taskService = processEngine.getTaskService();
Task task = taskService
.createTaskQuery()
.processDefinitionKey("helloworld")
.taskAssignee("hr")
.singleResult();
taskService.complete(task.getId());
三:示例二:负责人变量
负责人Assignee在实际开发过程中一般都不会写死,申请人写死难道只能这一个人能发起审批吗?所以一般负责人都是使用UEL表达式先定义一个变量,在启动实例或者其他时候给这个变量再赋值。
3.1 UEL表达式
UEL表达式类似于JSP中的ETL表达式,就是在 $
或者#
内可以写表达式,如引用一个变量值 $ assignee
、 $ xxx.assignee
,调用方法调用$对象.方法(execution)
,做一些简单的boolean条件运算,可以使用 &&
和 ||
连接多个条件,如$ xxx.day >= 3 || xxx.role == 'pm'
。
- 多个流程变量可以封装到一个POJO对象中,不过必须实现
Serializable
接口。 - 如果使用UEL指定Assignee时,启动流程实例时必须给变量赋值,候选人列表Candidate Users需要在启动流程实例时赋值。
3.2 BusinessKey
业务Key:员工发起请假申请时一般都要填写请假开始时间、请假结束时间、请假理由等和具体业务相关的数据,Activiti的25张表只会保存审批流程相关的数据,不会保存具体业务的数据,具体业务的数据需要开发人员自己定义表结构,自己维护,但是Activiti提供了一个字段(外键)可以保存和业务相关的数据,这个字段叫ACT_RU_EXECUTION.BUSINESS_KEY_
,通常我们会保存业务表的主键id,这样我们就可以通过BUSINESS_KEY_关联到员工的请假时间、请假原因等数据了。
3.3 流程定义ProcessDefinition和流程实例ProcessInstance
- 流程定义是定义.bpmn文件(相当于定义一个Java实体类文件Studeng.class),对应于act_re_procdef。
- 流程实例是根据流程定义文件发起一个具体的申请(相当于创建一个实例对象 Student zhangsan = new Student(“张三”) 对应于act_ru_execution中的
is_scope_ = 1
的那条记录。
/**
* 启动流程实例:发起申请请求
*/
@Test
public void startProcessInstance()
// 业务Key
String businessKey = "666";
// 变量:注意实际情况下候选人Assignee的值一般是用户的id而不是账号或者姓名。
Map<String, Object> variables = new HashMap<>();
variables.put("creator", "zhangsan");
variables.put("pm", "狗经理");
variables.put("hr", "小姐姐");
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
ProcessInstance processInstance = processEngine.getRuntimeService()
.startProcessInstanceByKey("helloworld", businessKey, variables);
System.out.println(processInstance.getId());
System.out.println(processInstance.getProcessInstanceId());
System.out.println(processInstance.getProcessDefinitionId());
四:数据库分析
4.1 创建表结构分析
ProcessEngines.getDefaultProcessEngine() 创建表的时候就会往act_ge_property中插入4个属性。
4.2 部署流程分析
部署流程时会保存3张表:act_re_deployment、act_re_procdef、act_re_bytearray。
4.3 启动流程
- act_ru_execution:流程实例和执行流,每发起一次申请就会生成两条记录,zhangsan和lisi分别发起就是4条数据。
- 插入第一条记录(流程实例),is_scope_ = 1 ,确定流程实例Id值。
- 插入第二条记录(第一个UserTask)被称为执行流。
- act_ru_task
- act_ru_identitylink
- act_ru_variable
启动流程时第一个任务就开始了。
同时第一个任务的负责人也将被记录下来。
当开始第一个任务的时候就会记录下来所有变量。
4.4 zhangsan完成流程
在完成任务之前可以先记录一些值。
当第一个任务完后就会卸磨杀驴被删除掉,同时下一个任务即将上位。
开始第二个任务,同时记录第二个任务的负责人。注意:第一个任务的执行人并没有删除。
开始第二个任务,第一个zhangsan的执行流被删除了,pm的执行流insert进来了。
历史表:zhangsan的任务已经完成结束了,要记录下来,同时第二个任务也已经开始了,但还没完成,所以没有结束时间。
act_ru_actinst相比于act_ru_taskinst数据更全一些,为记录工作流中的所有活动(包括开始、任务、结束等)。
第一个负责人和第二个负责人同时也被记录在历史上。
第一个任务完成后就会将所有的变量记录在历史中。
4.5 pm完成任务
4.6 hr完成任务
任务完成,一切运行时的数据都将清空。
一切结束的任务也将完整的记录在历史中。
以上是关于Activiti7工作流引擎:基础篇 Hello World的主要内容,如果未能解决你的问题,请参考以下文章