@ruoli
2016-09-07T10:06:27.000000Z
字数 8101
阅读 3451
Activiti
Activiti默认是不带有选人的功能的,它默认的是在调用complete方法的时候自动根据下一个节点的 assignee属性设置下一节点的候选人,也可设置candidate属性或者角色,提交到下一步,流程引擎自动解析为公有任务,需要具体执行人去认领。
但是并不是所有的业务逻辑都符合Activit规定的标准情况,适用于这种操作,用户提交时需要从几个候选人中选择一个,然后发送到下一个环节,被选择的审批人,在下一环节拥有待办,目前Activiti工作流暂不支持原生支持,需要自己扩展。
Activiti自带了23张表,其中有四张组织人员相关表:
1) act_id_group用户组信息表
2) act_id_info用户扩展信息表
3) act_id_membership用户与用户组对应信息表
4) act_id_user用户信息表
原生的Activiti人员解析,需要依赖Activiti内置的四张组织信息表,也提供了一些列的AIP让我们去操作这些表,插入和获取信息。
Activiti本身自带了简易的人员管理功能,角色配置,原生的做法是将人员和角色信息配置到工作流表中,工作流就可以自动解析环节处理时的角色,转换为为处理人,我们具体业务实现不用处理,但是这直接导致了三个问题:
第一:就是工作流自带的人员角色表过于简单,不一定能应对复杂的业务逻辑需求。
第二:需要维护两套人员角色信息,加重了程序设计的复杂性。
第三:不便于扩展,业务程序对工作流人员解析这块完全没有控制权,无法做到选人等业务需求。
首先我们无需管这四张表,也不 用往这些表中插入任何数据,这样就可以使Actriviti基于角色的选人失效,因为根据角色无法解析到人员。
实现我们自己的选人,同样依赖与流程图的属性配置,具体的逻辑是:
流程图配置好审批角色后,业务逻辑程序在提交下一步之前,提前获取到下一步的审批环节和审批角色,手工解析为多个人员,展示给用户,让其选择一个或多个,再以流程参数的形式设置到流程中,提交下一步,下一步审批环节识别到流程参数,绑定审批人员。
用户获取流程定义相关信息,ActDefinitionService.java示例为:
package modules.act.service;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.TaskService;
import org.activiti.engine.delegate.Expression;
import org.activiti.engine.impl.RepositoryServiceImpl;
import org.activiti.engine.impl.bpmn.behavior.MultiInstanceActivityBehavior;
import org.activiti.engine.impl.bpmn.behavior.NoneStartEventActivityBehavior;
import org.activiti.engine.impl.bpmn.behavior.UserTaskActivityBehavior;
import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity;
import org.activiti.engine.impl.pvm.PvmActivity;
import org.activiti.engine.impl.pvm.PvmTransition;
import org.activiti.engine.impl.pvm.delegate.ActivityBehavior;
import org.activiti.engine.impl.pvm.process.ActivityImpl;
import org.activiti.engine.impl.task.TaskDefinition;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.task.Task;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import common.utils.StringUtils;
import modules.act.entity.ActTransition;
/**
* 流程定义Service
* @author Ruoli
* 2016.08.23
*/
@Service
@Transactional(readOnly = true)
public class ActDefinitionService {
@Autowired
private RepositoryService repositoryService;
@Autowired
private TaskService taskService;
/**
* 查询任务对应的下一步路由
* @param taskId
* @return
*/
public List<ActTransition> getApprovalInfo(String taskId){
List<ActTransition> approvalList=new ArrayList<ActTransition>();
//获取当前环节对象
ActivityImpl activityImpl=this.getActivity(taskId);
List<PvmTransition> outTransitions = activityImpl
.getOutgoingTransitions();// 获取从某个节点出来的所有线路
for (PvmTransition tr : outTransitions) {
ActTransition transition=geTransition(tr);
//transition.getTaskRoleList(); //获取角色 集合
approvalList.add(transition);
}
return approvalList;
}
/**
* 根据TaskId获取流程定义环节对象
* @param taskId
* @return
*/
public ActivityImpl getActivity(String taskId){
Task task =taskService.createTaskQuery().taskId(taskId).singleResult();
if(task!=null){
ProcessDefinitionEntity def = (ProcessDefinitionEntity) ((RepositoryServiceImpl) repositoryService)
.getDeployedProcessDefinition(task.getProcessDefinitionId());
return def.findActivity(task.getTaskDefinitionKey());
}
return null;
}
/**
* 根据路由Id获取路由对象
* @param transitionId
* @return ActTransition
*/
public ActTransition geTransition(String processDefinitionId,String transitionId){
if(StringUtils.isNotEmpty(processDefinitionId) && StringUtils.isNotEmpty(transitionId)){
ProcessDefinitionEntity def = (ProcessDefinitionEntity) ((RepositoryServiceImpl) repositoryService)
.getDeployedProcessDefinition(processDefinitionId);
List<ActivityImpl> activityList=def.getActivities();
for(ActivityImpl activityImpl : activityList){
List<PvmTransition> outTransitions=activityImpl.getOutgoingTransitions();
for (PvmTransition pvmTransition : outTransitions) {
if(transitionId.equals(pvmTransition.getId())){
ActTransition actTransition=geTransition(pvmTransition);
return actTransition;
}
}
}
}
return null;
}
/**
* 根据连线对象获取下一步处理信息
* @param pvmTransition
* @return ActTransition
*/
private ActTransition geTransition(PvmTransition pvmTransition){
PvmActivity nextActivity = pvmTransition.getDestination();
ActTransition actTransition=new ActTransition();
actTransition.setId(pvmTransition.getId());
actTransition.setName(pvmTransition.getProperty("name")+"");
actTransition.setDescription(pvmTransition.getProperty("documentation")+"");
actTransition.setCondition(pvmTransition.getProperty("conditionText")+"");
actTransition.setTaskName(nextActivity.getProperty("name")+"");
//判断是否是UserTask
ActivityImpl activity=(ActivityImpl)nextActivity;
ActivityBehavior activityBehavior = activity.getActivityBehavior();
if (activityBehavior instanceof UserTaskActivityBehavior || activityBehavior instanceof MultiInstanceActivityBehavior) {
TaskDefinition taskDefinition=(TaskDefinition)nextActivity.getProperty("taskDefinition");
if(taskDefinition!=null){
Set<Expression> roleSet=taskDefinition.getCandidateGroupIdExpressions();
//List 用户存放下一步审批角色
List<String> roleList=new ArrayList<String>();
for(Expression expression:roleSet){
roleList.add(expression.getExpressionText());
}
actTransition.setTaskRoleList(roleList);
}
}
return actTransition;
}
/**
* 获取首环节处理角色
* @return
*/
public List<String> getFristNodeRole(String procDefKey){
List<String> roleList=new ArrayList<String>();
ProcessDefinition processDefinition=repositoryService.createProcessDefinitionQuery().processDefinitionKey(procDefKey)
.orderByProcessDefinitionVersion().desc().list().get(0);
ProcessDefinitionEntity def = (ProcessDefinitionEntity) ((RepositoryServiceImpl) repositoryService)
.getDeployedProcessDefinition(processDefinition.getId());
List<ActivityImpl> activityList=def.getActivities();
for(ActivityImpl activityImpl : activityList){
ActivityBehavior activityBehavior = activityImpl.getActivityBehavior();
if (activityBehavior instanceof NoneStartEventActivityBehavior) {
PvmActivity fristTask=activityImpl.getOutgoingTransitions().get(0).getDestination();
TaskDefinition taskDefinition=(TaskDefinition)fristTask.getProperty("taskDefinition");
Set<Expression> roleSet=taskDefinition.getCandidateGroupIdExpressions();
for(Expression expression:roleSet){
roleList.add(expression.getExpressionText());
}
break;
}
}
return roleList;
}
}
其中依赖实体类ActTransition.java 代码如下:
package modules.act.entity;
import java.util.List;
/**
* 下一步处理信息,此类主要用于人员或路由选择页面
* @author Ruoli
* 2016/08/23
*/
public class ActTransition {
private String id;//路由ID
private String name;//路由名称
private String description;//路由描述
private String condition;//路由条件
private String taskName;//下一步环节的名称
private List<String> taskRoleList; //下一步审批角色集合
//可根据业务需求新增更多字段
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getTaskName() {
return taskName;
}
public void setTaskName(String taskName) {
this.taskName = taskName;
}
public List<String> getTaskRoleList() {
return taskRoleList;
}
public void setTaskRoleList(List<String> taskRoleList) {
this.taskRoleList = taskRoleList;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getCondition() {
return condition;
}
public void setCondition(String condition) {
this.condition = condition;
}
}
/**
* 获取流程审批信息,提供发送时 展示选环节列表
* @param act
* @return
*/
@SuppressWarnings("unchecked")
protected List<Map<String, Object>> getApprovalTrack(String taskId){
if(StringUtils.isNotBlank(taskId)){
//1:获取路由信息
List<ActTransition> approvalList=actDefinitionService.getApprovalInfo(taskId); //actTaskService.getApprovalInfo(act.getTaskId());
//2:迭代路由
if(approvalList!=null){
//构建树形Tree-List
List<Map<String, Object>> resultList=new ArrayList<Map<String, Object>>();
for (ActTransition transition : approvalList) {
Map<String, Object> tempMap=new HashMap<String, Object>();
tempMap.put("id",transition.getId());
tempMap.put("name", transition.getTaskName());
tempMap.put("pId",1);
//此处还有验证路由条件的控制,暂时没有实现
//此处可以自己行增加 路由对应的人员信息,可根据角色进行解析,此示例只需要进行选路由即可
resultList.add(tempMap);
}
Map<String, Object> rootMap=new HashMap<String, Object>();
rootMap.put("id","1");
if(resultList.size()==0){
rootMap.put("name","暂无处理环节");
}else{
rootMap.put("name","可被选择的处理环节");
}
rootMap.put("pId","0");
rootMap.put("nocheck",true);//设置根节点不可选中
resultList.add(rootMap);
return resultList;
}
}
return null;
}