总体思路:

0: 初始化用户及用户组

1:上传并部署流程,启动流程

2: 创建流程实例

3:获取我的任务

4,执行审批操作

5,获取审批详情

问题一:Activiti6版本和activiti7版本最大的区别:

activiti7集成spring security 用户及用户组不在提供act_id_group、act_id_info、act_id_user等用户相关的表,而是使用security用户权限,所以如果项目集成spring security推荐使用7版本

Activiti6

问题二解决不能自动创建表:url: jdbc:mysql://最后面添加 &nullCatalogMeansCurrent=true

false:false为默认值,设置为该值后,Activiti在启动时,会对比数据库表中保存的版本,如果没有表或者版本不匹配时,将在启动时抛出异常。
true:设置为该值后,Activiti会对数据库中所有的表进行更新,如果表不存在,则Activiti会自动创建。
create-drop:Activiti启动时,会执行数据库表的创建操作,在Activiti关闭时,执行数据库表的删除操作。
drop-create:Activiti启动时,执行数据库表的删除操作在Activiti关闭时,会执行数据库表的创建操作。

spring.activiti.history-level = full

none:不保存任何的历史数据,因此,在流程执行过程中,这是最高效的。
activity:级别高于none,保存流程实例与流程行为,其他数据不保存。
audit:除activity级别会保存的数据外,还会保存全部的流程任务及其属性。audit为history的默认值。
full:保存历史数据的最高级别,除了会保存audit级别的数据外,还会保存其他全部流程相关的细节数据,包括一些流程参数等

以下我们按总体思路开始分析:

0:初始化用户及用户组

IdentityService:提供了对用户和用户组的管理功能。跟一般用户中心操作类似,通过IdentityService可以初始化用户之间的关系,建议跟部门关联起来,将部门关联起来

1:上传并部署流程并启动

RepositoryService:主要用于管理流程部署的数据

部署方式:

通过路径方式部署:repositoryService.createDeployment().addClasspathResource().deploy();

inputStream部署:repositoryService.createDeployment().addInputStream(fileName, fileInputStream).deploy();

字符串方式部署:repositoryService.createDeployment().addString(“名字”,“xml内容”)

压缩包方式部署:repositoryService.createDeployment().addZipInputStream(new ZipInputStream(zipStream)).deploy();

.deploy(); //执行部署

验证是否启动成功:repositoryService.createProcessDefinitionQuery().processDefinitionKey(“key”).count()

读取流程资源:

repositoryService.createProcessDefinitionQuery()
 repositoryService.createProcessDefinitionQuery().listPage(0,10)

删除部署:

repositoryService.deleteDeployment(deploymentId,true); //deleteDeployment方法有两个参数,第一个是部署ID,第二个参数true表示删除时,会同时把流程相关的流程数据(包括运行中的和已经结束的流程实例)一并删除掉

激活流程:repositoryService.activateProcessDefinitionById(processDefinitionId, true, null);

挂起流程:repositoryService.suspendProcessDefinitionById(processDefinitionId, true, null);

2:创建流程实例

RuntimeService:主要用于管理流程在运行时产生的数据(流程参数,事件,流程实例,以及执行流)以及对正在运行的流程进行操作的API

流程实例启动方式:

流程定义的key值:runtimeService.startProcessInstanceByKey(”processDefinitionKey“,vars);

流程实例挂起:runtimeService.suspendProcessInstanceById(processInstanceId);

流程实例激活:runtimeService.activateProcessInstanceById(processInstanceId);

流程实例 验证:

验证流程实例是否启动成功:Assert.assertNotNull(processInstance);

验证是否挂起: 反之激活Assert.assertTrue(runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult().isSuspended());

流程实例查询:

RuntimeService中有createExecutionQuery方法可以得到一个ExecutionQuery对象,该对象就可以根据执行流的相关数据查询执行流

RuntimeService提供了一个createProcessInstanceQuery的对象,可以查询对应的流程实例信息

执行流的查询: runtimeService.createExecutionQuery().processDefinitionKey(processDefinitionKey).list();

根据流程定义Key值查询正在运行的流程实例: runtimeService.createProcessInstanceQuery().processDefinitionKey(processDefinitionKey).list();

查询激活的流程实例:runtimeService.createProcessInstanceQuery().processDefinitionKey(processDefinitionKey).active().list();

查询挂起的流程:runtimeService.createProcessInstanceQuery().processDefinitionKey(processDefinitionKey).suspended().list();

删除流程实例:runtimeService.deleteProcessInstance(processInstanceId,“删除测试”);

创建流程实例的时候建议自己新建一张表,以方便记录获取查询,比如记录关联部门,方便后期查询自己创建历史

3:获取我的任务

TaskService: 提供了运行时任务的查询、领取、完成、删除以及变量设置等功能

此处才是重中之重,我在此浪费了很多时间。那我就简单描述一哈,一般流程设置执行人分为几种,有直接指定,有指定变量,有指定用户组等多种方式,

如果直接指定执行人,setAssignee(“user”)这种模式是没有问题,相对于很多演示demo也是这种,但是变量形式指定或者用户组指定时会出现assignee字段为null,比如以下方式执行执行人时,map.put(“users”,“a,b,c”);“users”对应流程图中的candidate #{users},多人用“,”分割,Act_ru_task表中:assignee字段是空的

通过

taskService.createTaskQuery()
        .taskAssignee(String.valueOf(SecurityUtils.getUserId()))

这种方式是获取不到数据,所以根据具体情况可以使用taskCandidateUser进行参与者,组任务查询,但是通过这种方式要注意一点,groupid,需要跟画流程图的时候指定的groupAssignee匹配的上,此处我也浪费了一些时间才整通

4,执行审批操作

if (task.getAssignee() == null) {
    taskService.claim(taskID,String.valueOf(String.valueOf(SecurityUtils.getUserId())));
}
if (hasVariables) {
    //带参数完成任务
    taskService.complete(taskID,variables);
} else {
    taskService.complete(taskID);
}

审批操作一般分为带参数完成,不带参数完成,如果是用户组任务,需要进行任务拾取,这里如果有兴趣的同学可以自行百度何为任务拾取。此处也建议新建一张表,存储审批意见,方便进行后期展示查询导出操作

5,获取审批详情

HistoryService:获取正在运行或者已经运行结束的流程实例信息

获取审批详情分为两种:一种就是HistoryService查询历史

另一种就是上面所说的创建自己表记录的操作记录

下面两种不常用,有兴趣的同学可以自行了解,这里就不做阐述了

FormService:流程和状态Task均可关联相关的业务数据

ManagementService:提供对流程引擎的管理和维护的功能

知识扩展:有助于扩展

ExecutionListener与TaskListener的区别:

public interface BaseExecutionListener extends Serializable {

  String EVENTNAME_START = "start";
  String EVENTNAME_END = "end";
  String EVENTNAME_TAKE = "take";
}

public interface BaseTaskListener extends Serializable {

  String EVENTNAME_CREATE = "create";
  String EVENTNAME_ASSIGNMENT = "assignment";
  String EVENTNAME_COMPLETE = "complete";
  String EVENTNAME_DELETE = "delete";

  String EVENTNAME_ALL_EVENTS = "all";
}

针对事件不同:根据代码块即可看出来

通知的代理不同:ExecutionListener:DelegateExecution 与TaskListener: DelegateTask

所遇问题

org.activiti.engine.ActivitiException: Unknown property used in expression: ${FormProperty_3qipis2==0}
解决办法:taskService.complete(task.getId(),variables); 删除第三个参数true
taskService.complete(task.getId(),variables,true)

说明:taskId(对应act_ru_task中的id_),variables(下一次任务所需要的参数),localScope(存储范围:本任务)