文档章节

Activiti中当候选组中只有一个受理人时进行自动签收的方法

李玉珏
 李玉珏
发布于 2015/03/03 13:44
字数 993
阅读 5292
收藏 7

        实际工作中,待办事项一般是通过用户ID进行查询的,这样比较简单、方便。在Activiti中,当绘制流程的人工任务节点时,为了便于日后维护,也为了更符合实际的场景,通常不会直接指定受理人,而是指定候选组,也就是通常说的角色。而很多时候,这个角色只有一个用户,但是在Activiti的实现中,这里面需要一个中间环节,就是签收,这个签收的过程,显得不够智能,用户会很自然的觉得多此一举,多了一步没必要的操作,那么能不能把这个环节省掉呢?本文将提供解决这个问题的方法。

        这个问题,只能研究下Activiti的源代码了,如果能找到扩展点,那这个问题就好办了,经过研究,发现并不难,工作量也不大,下面进行详细说明(本文前提是Activiti与Spring集成,其他环境请自行举一反三)。

        一、自定义DefaultActivityBehaviorFactory,自定义该类的目的是创建自定义的UserTaskActivityBehavior,自定义的DefaultActivityBehaviorFactory需要通过set方法注入到SpringProcessEngineConfiguration中;

        二、自定义UserTaskActivityBehavior,通过扩展handleAssignments方法,对于受理人、候选人和候选组进行处理。这里面需要注意的是,至于如何确定一个候选组只有一个用户,如何获取这个唯一的用户,开发者需要自行确定,下面的样例代码仅供参考。

import org.activiti.bpmn.model.UserTask;
import org.activiti.engine.impl.bpmn.behavior.UserTaskActivityBehavior;
import org.activiti.engine.impl.bpmn.parser.factory.DefaultActivityBehaviorFactory;
import org.activiti.engine.impl.task.TaskDefinition;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

public class ProcessActivityBehaviorFactory extends DefaultActivityBehaviorFactory implements ApplicationContextAware{
    
    private ApplicationContext applicationContext;
    @Override
    public UserTaskActivityBehavior createUserTaskActivityBehavior(
            UserTask userTask, TaskDefinition taskDefinition) {        
        ProcessUserTaskActivityBehavior taskActivityBehavior = (ProcessUserTaskActivityBehavior)applicationContext.getBean("taskActivityBehavior");
        taskActivityBehavior.setTaskDefinition(taskDefinition);
        return taskActivityBehavior;
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
}

 

    

import java.util.Collection;
import java.util.List;
import java.util.Map;

import org.activiti.engine.ActivitiException;
import org.activiti.engine.ActivitiIllegalArgumentException;
import org.activiti.engine.TaskService;
import org.activiti.engine.delegate.Expression;
import org.activiti.engine.impl.bpmn.behavior.UserTaskActivityBehavior;
import org.activiti.engine.impl.persistence.entity.TaskEntity;
import org.activiti.engine.impl.pvm.delegate.ActivityExecution;
import org.activiti.engine.impl.task.TaskDefinition;
import org.springframework.beans.factory.annotation.Autowired;

public class ProcessUserTaskActivityBehavior extends UserTaskActivityBehavior {
    @Autowired
    private TaskService taskService;
    
    public ProcessUserTaskActivityBehavior() {
        super(null);
    }
    
    public void setTaskDefinition(TaskDefinition taskDefinition){
        super.taskDefinition = taskDefinition;
    }

    public ProcessUserTaskActivityBehavior(TaskDefinition taskDefinition) {
        super(taskDefinition);
    }

    @Override
    protected void handleAssignments(TaskEntity task,ActivityExecution execution) {
        String assignee = null;
        List<String> candidateUserId = null,candidateGroupId = null;
        
        if (taskDefinition.getAssigneeExpression() != null) {
            assignee = (String) taskDefinition.getAssigneeExpression().getValue(execution);
            task.setAssignee(assignee,true,false);
        }
        
        if (taskDefinition.getOwnerExpression() != null) {
          task.setOwner((String) taskDefinition.getOwnerExpression().getValue(execution));
        }

        if (!taskDefinition.getCandidateGroupIdExpressions().isEmpty()) {
          for (Expression groupIdExpr : taskDefinition.getCandidateGroupIdExpressions()) {
            Object value = groupIdExpr.getValue(execution);
            if (value instanceof String) {
                candidateGroupId = extractCandidates((String) value);
                task.addCandidateGroups(candidateGroupId);
            } else if (value instanceof Collection) {
                task.addCandidateGroups((Collection) value);
            } else {
                throw new ActivitiIllegalArgumentException("Expression did not resolve to a string or collection of strings");
            }
          }
        }

        if (!taskDefinition.getCandidateUserIdExpressions().isEmpty()) {
          for (Expression userIdExpr : taskDefinition.getCandidateUserIdExpressions()) {
            Object value = userIdExpr.getValue(execution);
            if (value instanceof String) {
              candidateUserId = extractCandidates((String) value);
              task.addCandidateUsers(candidateUserId);
            } else if (value instanceof Collection) {
              task.addCandidateUsers((Collection) value);
            } else {
              throw new ActivitiException("Expression did not resolve to a string or collection of strings");
            }
          }
        }
        
        if (assignee == null && candidateUserId == null && candidateGroupId.size() ==1){
            String groupId = candidateGroupId.get(0);
            //下面的代码开发者自行确定处理方法
            String sql = "SELECT USER_ID FROM SYS_ROLE_USER WHERE ROLE_ID = '" + groupId + "' AND ROLE_TYPE = '3'";
            CoreTemplate coreTemplate = CoreContextContainer.getContext().getCoreTemplate();
            List data = coreTemplate.find(sql,null,true);
            
            if (data.size() == 1){
                String userId = (String)((Map)data.get(0)).get("user_id");
                taskService.claim(task.getId(),userId);//符合条件的自动签收
            }
        }
    }
}

 

        下面是对应的Spring配置文件,这里面特别需要注意的是,taskActivityBehavior不能是单例的,相应的scope值为prototype。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
            xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
                            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd">    
    <bean id="processEngineConfiguration" class="com.process.ProcessEngineConfiguration">        
          <property name="activityBehaviorFactory" ref="activityBehaviorFactory"/>          
      </bean>      
      <bean id="activityBehaviorFactory" class="com.process.ProcessActivityBehaviorFactory"/>
      <bean id="taskActivityBehavior" class="com.process.ProcessUserTaskActivityBehavior" scope="prototype"/>
</beans>

 

        以上代码在Activiti5.15.1版本中测试通过。

© 著作权归作者所有

共有 人打赏支持
李玉珏

李玉珏

粉丝 279
博文 60
码字总数 102475
作品 0
沈阳
技术主管
加载中

评论(3)

d
dizh
学习了~
李玉珏
李玉珏

引用来自“feng84251542”的评论

缺少com.process.ProcessEngineConfiguration的代码

这个和这个功能没关系,你用系统的就行
feng84251542
feng84251542
缺少com.process.ProcessEngineConfiguration的代码
能提供下ProcessEngineConfiguration类的源码吗?

@liyuj 你好,想跟你请教个问题: 看了你的 “Activiti中当候选组中只有一个受理人时进行自动签收的方法”这篇文章,我觉得正好是我需要的,但是整合进去,发现用org.activiti.spring.Sprin...

双曲线
2015/07/22
196
2
activiti参考5-任务TASK

一、概要 1,涉及TASK的表主要是:ACTRUTASK,ACTHITASKINST(见参考-activiti表); 2,任务主要有:人工任务(usertask),服务任务(servicetask)等; 3,候选人/候选组(candidate):可...

安世博
2014/07/02
11.2K
4
activiti学习笔记8-签收与委托 操作

签收与委托对初学者是比较不好理解的内容,但是知道原理以后,就非常容易了。 一,数据库表 先看看activiti中关于TASK的数据库表: 其中有两个字段:OWNER,ASSIGNEE 这两个字段的意义是: ...

安世博
2014/12/01
5.4K
2
Activiti用户任务分配

一、前言 上篇博文《浅谈Activiti工作流引擎用户管理》中已介绍了如何自定义自己的用户管理模块。然而困恼大多数新手的另一个问题:如何将任务分配给有层级关系的组织结构用户呢?例如,我只...

qllinhongyu
2015/05/30
0
0
Activiti快速入门Demo kft-activiti-demo 1.10 发布

kft-activiti-demo 1.10 发布,改进内容包括: 集成了diagram-viewer,目前提供了三种流程跟踪方式 引擎在后台生成图片标记当前节点 自己写js代码实现跟踪(比较灵活) diagram-viewer方式(...

咖啡兔
2014/04/18
3.6K
2

没有更多内容

加载失败,请刷新页面

加载更多

12-利用思维导图梳理JavaSE-

12-利用思维导图梳理JavaSE- 主要内容 1.线程概念 2.线程开发 3.线程的状态 4.线程的同步和死锁 5.Java5.0并发库类 QQ/知识星球/个人WeChat/公众号二维码 本文为原创文章,如果对你有一点点的...

飞鱼说编程
10分钟前
0
0
JAVA集合之ArrayList

一、前言 Java 集合类提供了一套设计良好的支持对一组对象进行操作的接口和类,JAVA常用的集合接口有4类,分别是: Collection:代表一组对象,每一个对象都是它的子元素 Set:不包含重复元素...

木木匠
31分钟前
1
0
转:XMLHttpRequest2 新技巧

”XMLHttpRequest 的异步调用网上找的例子运行没问题,但稍微改了一点点就报错”InvalidStateError: XMLHttpRequest has an invalid context“。断断续续 搞了3天终于通了,可以接收二进制文...

SamXIAO
50分钟前
2
0
=====D服务器定时任务=====

Linux定时任务 crontab linux系统是有cron这个系统服务来控制的,Liunx系统上包含很多的计划性工作,使用者自己可以设置计划任务,所以linux系统提供了使用者控制计划任务的命令 crontab的启...

覃光林
59分钟前
1
0
xilinx资源

本系列教学视频由赛灵思高级战略应用工程师带领你:从零开始,一步步深入 掌握 HLS 以及 UltraFAST 设计方法,帮助您成为系统设计和算法加速的大拿! http://www.eetrend.com/topics/2018-0...

whoisliang
今天
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部