文档章节

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

李玉珏
 李玉珏
发布于 2015/03/03 13:44
字数 993
阅读 5431
收藏 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版本中测试通过。

© 著作权归作者所有

共有 人打赏支持
李玉珏

李玉珏

粉丝 298
博文 63
码字总数 106838
作品 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

没有更多内容

加载失败,请刷新页面

加载更多

MariaDB 服务器在 MySQL Workbench 备份数据的时候出错如何解决

服务器是运行在 MariaDB 10.2 上面的,在使用 MySQL Workbench 出现错误: mysqldump: Couldn't execute 'SELECT COLUMN_NAME, JSON_EXTRACT(HISTOGRAM, '$."number-of-buckets-specified"'......

honeymose
今天
3
0
apache顶级项目(二) - B~C

apache顶级项目(二) - B~C https://www.apache.org/ Bahir Apache Bahir provides extensions to multiple distributed analytic platforms, extending their reach with a diversity of s......

晨猫
今天
6
0
day152-2018-11-19-英语流利阅读

“超级食物”竟然是营销噱头? Daniel 2018-11-19 1.今日导读 近几年来,超级食物 superfoods 开始逐渐走红。不难发现,越来越多的轻食餐厅也在不断推出以超级食物为主打食材的健康料理,像是...

飞鱼说编程
今天
14
0
SpringBoot源码:启动过程分析(二)

接着上篇继续分析 SpringBoot 的启动过程。 SpringBoot的版本为:2.1.0 release,最新版本。 一.时序图 一样的,我们先把时序图贴上来,方便理解: 二.源码分析 回顾一下,前面我们分析到了下...

Jacktanger
昨天
4
0
Apache防盗链配置,Directory访问控制,FilesMatch进行访问控制

防盗链配置 通过限制referer来实现防盗链的功能 配置前,使用curl -e 指定referer [root@test-a test-webroot]# curl -e "http://www.test.com/1.html" -x127.0.0.1:80 "www.test.com/1.jpg......

野雪球
昨天
7
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部