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

实际工作中,待办事项一般是通过用户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版本中测试通过。

时间: 2024-10-09 07:26:26

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

Linux中用户和组中认证库和解析库的文件格式以及默认参数定义文件

解析库:/etc/passwd,/etc/group    组名和组的对应关系 认证库:/etc/shadow,/etc/gshadow  组密码的相关内容存储位置 与用户账户和组账户相关的文件有: /etc/passwd /etc/group /etc/shadow /etc/gshadow /etc/default/useradd /etc/login.defs(登录的默认属性) /etc/skel(家目录默认存储文件) /etc/passwd(用户的相关信息): 用户账户在/etc/pas

mybatis高级(2)_数据库中的列和实体类不匹配时的两种解决方法_模糊查询_只能标签

<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="cn.cnsdhzzl.dao.StudentDao&q

返回一个随机数组中的子数组中的数相加最大的和(二)

设计思想: 随机生成数组(含有正数与负数). 求所有子数组:按数组长度进行数组的划分(因为要求数组是连续的). 计算:从第一个数开始做加法,若和大于第二个数,则继续加下一个数(若加上第三个数的和大于第三个数,则重复进行此操作:小于第三个数,则舍掉前面所有数,并继续就重复进行此操作):若小于第二个数,则舍掉第一个数. 实现代码: #include <iostream> #include<time.h> using namespace std; int maxSum(int* a, i

活动目录 powershell 从组中 添加\删除 用户

某组织的ou中的账户可能经常需要移动,每个部门ou都有部门组,以dep_开头,如果账号从ou1移动到ou2,则账号需要从ou1中的部门组中删除,同时,要添加到ou2的部门组中,脚本如下: $ConfirmPreference="none"   #关闭confirm确认提示   $ou_all=Get-ADOrganizationalUnit -Filter * -SearchBase "OU=sales_ou,DC=test,DC=com"  #查询特定ou    

使用windows打开一个文本时,鼠标右键找不到notepad

[出现问题]:notepad++已经安装在Windows中,但是当要打开一个文件时,鼠标右键却找不到notepd++ [解决办法]:打开notepad++后记事本,输入: Windows Registry Editor Version 5.00 [HKEY_CLASSES_ROOT\*\Shell\NotePad++] [HKEY_CLASSES_ROOT\*\Shell\NotePad++\Command] @="\"E:\notepad\az" \"%1\&qu

定义一个带参带返回值的方法,实现输出随机数数组

public class mains { public static void main(String[] args) { // 创建对象,对象名为hello mains hello = new mains(); // 调用方法并将返回值保存在变量中 int[] nums = hello.getArray(8); // 将数组转换为字符串并输出 System.out.println(Arrays.toString(nums)); } /* * 功能:创建指定长度的int型数组,并生成100以内随

BOS项目 第11天(activiti工作流第三天,流程实例管理、项目中的用户和角色同步到activiti的用户和组表、设计物流配送流程、启动物流配送流程、组任务操作(查询、拾取)、个人任务操作(查询、办理))

BOS项目笔记 第11天 今天内容安排: 1.流程实例管理(查询.查看运行状态) 2.将bos系统中的用户和角色同步到activiti的用户和组表 3.设计物流配送流程 4.启动物流配送流程 5.组任务操作(查询.拾取) 6.个人任务操作(查询.办理) 1. 流程实例管理 1.1 查询流程实例列表 第一步:创建一个流程实例管理Action,提供list方法,查询流程实例列表数据 第二步:配置struts.xml 第三步:提供processinstance.jsp页面,展示列表数据 <s:iter

OC中动态创建可变数组的问题.有一个数组,数组中有13个元素,先将该数组进行分组,每3个元素为一组,分为若干组,最后用一个数组统一管理这些分组.(要动态创建数组).两种方法

<span style="font-size:24px;">//////第一种方法 // NSMutableArray *arr = [NSMutableArray array]; // for (int i = 0; i < 13; i ++) { // [arr addObject:[NSString stringWithFormat:@"lanou%d",i + 1]]; // } // NSLog(@"%@",arr);

面试题:一个整型数组中各元素排列组合得到的最大的一个数 ,比如,1,3,9,11,23,233,911 要得到:9,911,3,233,23,11,1

package com.alibaba.interview; import java.util.Random; /** * @Author: weblee * @Email: [email protected] * @Blog: http://www.cnblogs.com/lkzf/ * @Time: 2014年10月25日下午2:58:39 * ************* function description *************** *一个整型数组中各元素排列组合得到的最大的一个