总体思路:
0: 初始化用户及用户组
1:上传并部署流程,启动流程
2: 创建流程实例
3:获取我的任务
4,执行审批操作
5,获取审批详情
问题一:Activiti6版本和activiti7版本最大的区别:
activiti7集成spring security 用户及用户组不在提供act_id_group、act_id_info、act_id_user等用户相关的表,而是使用security用户权限,所以如果项目集成spring security推荐使用7版本
问题二解决不能自动创建表: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级别的数据外,还会保存其他全部流程相关的细节数据,包括一些流程参数等
以下我们按总体思路开始分析:
IdentityService:提供了对用户和用户组的管理功能。跟一般用户中心操作类似,通过IdentityService可以初始化用户之间的关系,建议跟部门关联起来,将部门关联起来
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);
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,“删除测试”);
创建流程实例的时候建议自己新建一张表,以方便记录获取查询,比如记录关联部门,方便后期查询自己创建历史
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匹配的上,此处我也浪费了一些时间才整通
if (task.getAssignee() == null) {
taskService.claim(taskID,String.valueOf(String.valueOf(SecurityUtils.getUserId())));
}
if (hasVariables) {
//带参数完成任务
taskService.complete(taskID,variables);
} else {
taskService.complete(taskID);
}
审批操作一般分为带参数完成,不带参数完成,如果是用户组任务,需要进行任务拾取,这里如果有兴趣的同学可以自行百度何为任务拾取。此处也建议新建一张表,存储审批意见,方便进行后期展示查询导出操作
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(存储范围:本任务)