Activiti第三天 采购流程监控 流程变量 连线分支
第三天:
采购流程监控:(重点)
进行采购业务流程的监控:
查询当前正在运行的流程
实现动态图(在流程定义图上标出当前结点的位置,使用红色的框)
查询结束的流程
查询某个流程下历史任务(从流程开始运行到当前所经历的所有任务)
查询某个用户所办理的历史任务
流程变量:(重点)
Global全局变量(掌握)
Local局部变量(了解)
连接分支:
需求流程变量支持
设置连接的candition条件实现分支
案例1(重点)
案例2(重点)
1 复习
什么是流程定义 ?
流程定义是按照bpmn2.0标准定义业务流程,将流程定义的文件(.bpmn和.png(不是必须的))部署到activiti中,activiti就可以管理该业务流程。
什么是流程实例 ?
参与者(可以用户,也可以程序)按照流程定义发起一个流程,这个流程就是一个流程实例 。
流程定义的内容就是一个静态文件(.bpmn),流程实例的内容是该 流程的执行过程(动态)。
如何启动一个流程实例 ?
常用方式:启动一个流程实例时指定一个业务标识。
// 业务标识 ,如果 是采购流程就是采购单id
String businessKey = "001";
// 启动流程实例时指定业务标识
String processDefinitionKey = "purchasingflow";
ProcessInstance processInstance = runtimeService
.startProcessInstanceByKey(processDefinitionKey, businessKey);
businessKey:业务标识,作用:通过activiti的api查询activiti的流程数据时,可以通过businessKey关联查询业务系统 的数据,通常业务标识记录业务系统 表的主键,比如:如果采购流程,businesskey就是采购单id,如果是请假流程,businessKey就是请假单(请假信息表)的id。
启动一个流程实例 后,该 流程运行到第一个结点,activiti需要给该 任务结点分配任务负责人。
任务分配三种方式:
第一种:采用固定分配方法,设置task结点的assignee(任务负责人)属性,不常用。
第二种:采用UEL表达式,表达使用流程变量设置任务负责人,在企业开发中常用。
第三种:采用监听器(自定义监听器实现 TaskListener接口),可以在监听器中扩展代码,在企业开发中常用。
查询待办任务:
查询待办任务中如果包括 业务系统 数据,如果查询?
通过Taskid得到任务所属的流程实例id
通过流程实例id得到流程实例对象ProcessInstance。
从ProcessInstance获取businessKey
通过businessKey关联查询业务数据
办理任务(完成任务):
需要参数:任务id(activiti的api要求),用户id(进行权限校验使用)
在完成任务之前需要校验该 用户是否有该 任务的完成权限。
Activiti开发步骤:
1、在需求阶段,分析出业务流程
2、设计阶段,确定哪些业务流程由activiti管理,对工作流管理的流程进行流程定义
流程定义时和功能设计同步进行:
1》确定流程启动所对应的功能
2》确定流程执行中哪些功能和流程结点对应,哪个功能可以将流程向后推进一步
Activiti开发遵循原则:
1、角色分工明确,activiti负责流程管理 ,业务系统 负责业务功能。
2、业务系统 中通常在service层将activiti和控制层、持久层进行隔离(解耦),比如在业务功能中需要查询activiti的流程数据,需要自定义一个对象存储activiti的数据。
3、数据共享问题,在activiti中存储businesskey(业务标识),通过businesskey查询业务系统 数据,在业务系统 中存储activiti的标识(比如在采购单中存储流程实例 的id),在查询业务数据时通过此流程实例 id查询activiti的数据。达到目标:activiti和业务系统 能互相关联查询。
2 查询当前正在运行的流程
2.1 需求
查询系统 中没有结束的采购流程有哪些,查询当前运行到哪个结点,及所完成的任务列表。
查询内容:流程实例 id、当前结点、采购单名称、采购金额、下单人。
2.2 实现
分析:
流程实例 id、当前结点:
从activiti的数据库(act_ru_execution流程实例执行表)查询。
通过RuntimeService查询当前运行的流程实例 。
采购单名称、采购金额、下单人:
从业务系统数据库(pur_bus_order采购单表)查询。
通过采购单id查询,采购单id就是activiti流程实例表中存储的businessKey。
dao
通过采购单id查询采购单表的记录:
使用逆向工程 生成的 mapper
service
接口功能:查询当前正在运行的流程
接口参数:查询条件,如果此接口可以查询所有业务流程实例,查询条件必须将流程定义的key(可能包括:采购流程、请假流程。。)传入
接口实现:
通过RuntimeService查询当前运行的流程实例
得到businessKey关联查询业务系统 数据
@Override
public List<OrderCustom> findActivityOrderList() throws Exception {
// 创建查询对象
ProcessInstanceQuery processInstanceQuery = runtimeService
.createProcessInstanceQuery();
// 设置查询条件
//流程定义 key
String processDefinitionKey = ResourcesUtil.getValue(
"diagram.purchasingflow", "purchasingProcessDefinitionKey");
// 指定 流程定义key只查询该类流程的实例,比如key为采购流程,只查询采购流程实例
processInstanceQuery.processDefinitionKey(processDefinitionKey);
//当前排序字段
processInstanceQuery.orderByProcessInstanceId().desc();
// 获取查询列表
List<ProcessInstance> list = processInstanceQuery.list();
// 单独 定义一个list,list中包括自定义的pojo(OrderCustom包括 流程实例 信息和业务系统 信息)
List<OrderCustom> orderList = new ArrayList<OrderCustom>();
for (ProcessInstance processInstance : list) {
OrderCustom orderCustom = new OrderCustom();
// 比如key为采购流程,这个key就是采购单id
String businesskey = processInstance.getBusinessKey();
// 根据 businessKey获取采购单信息
PurBusOrder purBusOrder = purBusOrderMapper.selectByPrimaryKey(businesskey);
//将采购单信息拷贝到orderCustom中
BeanUtils.copyProperties(purBusOrder, orderCustom);
//向orderCustom中填充流程实例 信息
//当前运行的结点
orderCustom.setActivityId(processInstance.getActivityId());
orderList.add(orderCustom);
}
return orderList;
}
action
当前运行流程查询方法:
页面
测试
测试步骤:
查询当前运行的流程,对照act_ru_execution表。
员工创建一个新的采购单,查询当前运行的流程应该包括 该 流程。
完成一个流程,查询当前运行的流程是查询不到。
如果有查询条件,对每个查询条件进行测试。
3 当前流程动态图
3.1 需求
通过图形展示出当前流程中当前结点位置。
效果:
在当前结点用红框标识:
3.2 分析
实现1:根据流程实例 id获取图形
通过/flow/queryProcessDefinitionResource.action?processDefinitionId=XXXXXX& resourceType=png 这个url展示一个业务流程图。
processDefinitionId如何获取:
根据 流程实例的id查询出流程实例 的对象,从对象 中获取processDefinitionId。
实现 2:获取当前结点的坐标及宽高,根据 坐标及宽高使用红色的div层在html显示。
从流程定义文件中获取:
代码如下:
// 根据 流程定义 id查询流程定义 实体对象
ProcessDefinitionEntity processDefinitionEntity = (ProcessDefinitionEntity) repositoryService
.getProcessDefinition(processDefinitionId);
//从流程定义 实体对象查询结点的坐标和宽高
ActivityImpl activityImpl = processDefinitionEntity.findActivity(activityId);
int activity_x= activityImpl.getX();//坐标
int activity_y = activityImpl.getY();//坐标
int activity_width = activityImpl.getWidth();//宽
int activity_height = activityImpl.getHeight();//高
最终实现 :页面上显示图形,再显示div层,图形结点的坐标及宽高与div层一致
3.3 图形在页面显示
action
在FlowAction添加方法:
根据流程实例 id展示动态图形:
//当前运行流程中当前结点图形
@RequestMapping("/queryActivityMap")
public String queryActivityMap(Model model,String processInstanceId)throws Exception{
//根据 流程实例的id查询出流程实例 的对象,从对象 中获取processDefinitionId。
ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
String processDefinitionId=processInstance.getProcessDefinitionId();
// 将流程定义 id传到页面,用于图形显示
model.addAttribute("processDefinitionId", processDefinitionId);
//
return "flow/queryActivityMap";
}
页面
定义显示动态图形页面:
定义 img,src=/flow/queryProcessDefinitionResource.action?processDefinitionId=${processDefinitionId}& resourceType=png
<!-- 流程图 -->
<img style="position: absolute; top: 0px; left: 0px;"
src="${baseurl}flow/queryProcessDefinitionResource.action?processDefinitionId=${processDefinitionId}&resourceType=png">
根据action传来的坐标和宽高,定义 div层:
<!-- 流程图中当前活动框 -->
<div
style="position: absolute;border:1px solid red;width: ${activity_width }px;height:${activity_height }px;top:${activity_y }px;left: ${activity_x }px;"></div>
在当前运行流程页面,添加查询动态图形连接:
<td class=category><a
href="${baseurl }flow/queryActivityMap.action?processInstanceId=${order.processinstanceId}"
target="_blank">查看流程图</a></td>
4 查询结束的流程
4.1 需求
需求1、查询已结束 的采购流程。
查询内容:流程实例 id、执行开始时间、执行结束时间、采购单名称、采购金额、下单人
需求2、对已结束的采购流程进行统计,比如按分类统计采购金额总数。
4.2 实现查询已结束 的采购流程
api
//查询历史 流程实例
@Test
public void queryHistoryProcessInstance(){
HistoryService historyService = processEngine.getHistoryService();
//创建历史流程实例 查询对象
HistoricProcessInstanceQuery historicProcessInstanceQuery = historyService.createHistoricProcessInstanceQuery();
//设置查询条件
//指定流程定义key,只查询某个业务流程的实例
String processDefinitionKey= "purchasingflow";
historicProcessInstanceQuery.processDefinitionKey(processDefinitionKey);
//设置只查询已完成的流程实例
historicProcessInstanceQuery.finished();
//数据列表
List<HistoricProcessInstance> list = historicProcessInstanceQuery.list();
for(HistoricProcessInstance historicProcessInstance:list){
System.out.println("==============================");
System.out.println("流程实例所属流程定义id :"
+ historicProcessInstance.getProcessDefinitionId())