之前一直是activiti这个25张表里面自己操作,就相当于一个demo,现在我们要和自己的业务进行整合
流程实例(ProcessInstance)代表流程定义的执行实例。
一个流程实例包括了所有的运行节点。我们可以利用这个对象来了解当前流程实例的进度等信息。
例如:用户或程序按照流程定义内容发起一个流程,这就是一个流程实例。
流程定义和流程实例的图解:
流程定义部署在activiti后,就可以在系统中通过activiti去管理该流程的执行,执行流程表示流程的一次执行。
比如部署系统出差流程后,如果某用户要申请出差这时就需要执行这个流程,如果另外一个用户也要申请出差则也需要执行该流程,每个执行互不影响,每个执行是单独的流程实例。
启动流程实例时,指定的businesskey,就会在act_ru_execution #流程实例的执行表中存储businesskey。
Businesskey:业务标识,通常为业务表的主键,业务标识和流程实例一一对应。业务标识来源于业务系统。存储业务标识就是根据业务标识来关联查询业务系统的数据。
比如:出差流程启动一个流程实例,就可以将出差单的id作为业务标识存储到activiti中,将来查询activiti的流程实例信息就可以获取出差单的id从而关联查询业务系统数据库得到出差单信息。
就是我们在我们的业务系统里面,创建一个申请单,那么我们的业务系统里面有申请单的表,写好的信息是保存在我们的业务系统的数据库的表里面的,这个表里面有id,在保存的时候,将这个id也保存到25张表里面,因为我们要使用activiti,所以要创建流程实例才可以,在创建流程实例的时候,就可以将数据的id 保存到activiti里面;
=================================================
我们业务要结合activiti,就需要将我们的数据关联到activiti; 在启动流程的时候,就需要将我们的数据关联到activiti; 也就是指定的businesskey;
/**
* 启动流程实例,添加businessKey
*/
@Test
public void addBusinessKey(){
// 1、得到ProcessEngine
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
// 2、得到RunTimeService
RuntimeService runtimeService = processEngine.getRuntimeService();
// 3、启动流程实例,同时还要指定业务标识businessKey,也就是出差申请单id,这里是1001
ProcessInstance processInstance = runtimeService.
startProcessInstanceByKey("myEvection","1001");
// 4、输出processInstance相关属性
System.out.println("业务id=="+processInstance.getBusinessKey());
}
我们的业务系统里面有一个出差申请单,这个单的id是1001,在创建申请单的时候,就创建流程实例,将1001保存到流程实例里面;
以上代码执行完成之后,就将我们的1001单号的申请单和我们的出差流程进行结合了;
将1001保存在了哪个表里面?
以上2个表里面进行了保存1001;
某些情况可能由于流程变更需要将当前运行的流程暂停而不是直接删除,流程暂停后将不会继续执行。
就是有多个申请单,现在多个申请单要一同挂起;
操作流程定义为挂起状态,该流程定义下边所有的流程实例全部暂停:
流程定义为挂起状态该流程定义将不允许启动新的流程实例,同时该流程定义下所有的流程实例将全部挂起暂停执行。
/**
* 全部流程实例挂起与激活
*/
@Test
public void SuspendAllProcessInstance(){
// 获取processEngine
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
// 获取repositoryService
RepositoryService repositoryService = processEngine.getRepositoryService();
// 查询流程定义的对象
ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().
processDefinitionKey("myEvection").
singleResult();
// 得到当前流程定义的实例是否都为暂停状态
boolean suspended = processDefinition.isSuspended();
// 流程定义id
String processDefinitionId = processDefinition.getId();
// 判断是否为暂停
if(suspended){
// 如果是暂停,可以执行激活操作 ,参数1 :流程定义id ,参数2:是否激活,参数3:激活时间
repositoryService.activateProcessDefinitionById(processDefinitionId,
true,
null
);
System.out.println("流程定义:"+processDefinitionId+",已激活");
}else{
// 如果是激活状态,可以暂停,参数1 :流程定义id ,参数2:是否暂停,参数3:暂停时间
repositoryService.suspendProcessDefinitionById(processDefinitionId,
true,
null);
System.out.println("流程定义:"+processDefinitionId+",已挂起");
}
}
执行完成以上的代码,数据库流程定义的数据,这个字段就变为2
变为2就是 当前的流程定义已经挂起;
再次执行一下代码,我们可以看到变为1,就是启动了
操作流程实例对象,针对单个流程执行挂起操作,某个流程实例挂起则此流程不再继续执行,完成该流程实例的当前任务将报异常。
/**
* 单个流程实例挂起与激活
*/
@Test
public void SuspendSingleProcessInstance(){
// 获取processEngine
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
// RuntimeService
RuntimeService runtimeService = processEngine.getRuntimeService();
// 查询流程定义的对象
ProcessInstance processInstance = runtimeService.
createProcessInstanceQuery().
processInstanceId("15001").
singleResult();
// 得到当前流程定义的实例是否都为暂停状态
boolean suspended = processInstance.isSuspended();
// 流程定义id
String processDefinitionId = processInstance.getId();
// 判断是否为暂停
if(suspended){
// 如果是暂停,可以执行激活操作 ,参数:流程定义id
runtimeService.activateProcessInstanceById(processDefinitionId);
System.out.println("流程定义:"+processDefinitionId+",已激活");
}else{
// 如果是激活状态,可以暂停,参数:流程定义id
runtimeService.suspendProcessInstanceById( processDefinitionId);
System.out.println("流程定义:"+processDefinitionId+",已挂起");
}
}
/**
* 测试完成个人任务
*/
@Test
public void completTask(){
// 获取引擎
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
// 获取操作任务的服务 TaskService
TaskService taskService = processEngine.getTaskService();
// 完成任务,参数:流程实例id,完成zhangsan的任务
Task task = taskService.createTaskQuery()
.processInstanceId("15001")
.taskAssignee("rose")
.singleResult();
System.out.println("流程实例id="+task.getProcessInstanceId());
System.out.println("任务Id="+task.getId());
System.out.println("任务负责人="+task.getAssignee());
System.out.println("任务名称="+task.getName());
taskService.complete(task.getId());
}
单个实例挂起,操作的表是
变为2,这个流程就挂起了
以上是单个任务挂起了,那么挂起的任务还能往下走嘛,我们执行下面的代码,然后输出是:
在进行业务流程建模时指定固定的任务负责人, 如图: 并在 properties 视图中,填写 Assignee 项为任务负责人。
固定就是在流程部署的时候,就创建了当前的任务谁做,但是这样是不对的,因为要动态设置;
由于固定分配方式,任务只管一步一步执行任务,执行到每一个任务将按照 bpmn 的配置去分配任务负责人。
企业中不能这样,所以这个负责人需要动态的设置
Activiti 使用 UEL 表达式, UEL 是 java EE6 规范的一部分, UEL(Unified Expression Language)即 统一表达式语言, activiti 支持两个 UEL 表达式: UEL-value 和 UEL-method。
assignee 这个变量是 activiti 的一个流程变量,
或者使用这种方式定义:
user 也是 activiti 的一个流程变量, user.assignee 表示通过调用 user 的 getter 方法获取值。
如图:
userBean 是 spring 容器中的一个 bean,表示调用该 bean 的 getUserId()方法。
再比如: ${ldapService.findManagerForEmployee(emp)} ldapService 是 spring 容器的一个 bean,findManagerForEmployee 是该 bean 的一个方法,emp 是 activiti 流程变量, emp 作为参数传到 ldapService.findManagerForEmployee 方法中。
表达式支持解析基础类型、 bean、 list、 array 和 map,也可作为条件判断。 如下: ${order.price > 100 && order.price < 250}
就是我们在画流程图的时候,这个负责人不写死了,直接使用变量,之后,我们在创建流程实例的时候,将这些变量进行赋值;举一个例子,我们在画流程的时候,使用了变量,之后将这个流程进行部署到数据库,之后创建流程实例的时候,就需要对这些变量进行赋值了,创建流程实例的代码就变为了
我们重新画一个bump的文件,里面的负责人是使用变量进行定义的
把以上我们新创建的流程部署到数据库,执行代码
部署完毕之后是这个:
我们看数据库:
以上只是部署成功,现在我们要创建流程实例,就是在创建流程实例的时候,动态的添加谁审批;
在启动流程实例时设置流程变量,如下:
/**
* 设置流程负责人
*/
@Test
public void assigneeUEL(){
// 获取流程引擎
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
// 获取 RuntimeService
RuntimeService runtimeService = processEngine.getRuntimeService();
// 设置assignee的取值,用户可以在界面上设置流程的执行
Map<String,Object> assigneeMap = new HashMap<String,Object>();
assigneeMap.put("assignee0","张三");
assigneeMap.put("assignee1","李经理");
assigneeMap.put("assignee2","王总经理");
assigneeMap.put("assignee3","赵财务");
// 启动流程实例,同时还要设置流程定义的assignee的值
runtimeService.startProcessInstanceByKey("assigneeUEL",assigneeMap);
// 输出
System.out.println(processEngine.getName());
}
执行完成以上的 代码 执行成功后,可以在act_ru_variable表中看到刚才map中的数据
由于使用了表达式分配,必须保证在任务执行过程表达式执行成功,比如: 某个任务使用了表达式${order.price > 100 && order.price < 250},当执行该任务时必须保证 order 在 流程变量中存在,否则 activiti 异常。