• Activiti动态设置办理人扩展


    Activiti动态设置办理人扩展

    作者:Jesai

    扩展是要求对Activiti基础有一定的功底的

    我们一直在努力,不是为了改变世界,只是不让世界去改变我们。

    关键词:Assignee、Candidate users、Candidate groups;setAssignee、taskCandidateUser、taskCandidateGroup

    主要解决问题:Activiti动态给任务节点设置办理人。

    情景:

    我们在做工作流开发,学习的时候一般都有这么一个过程:

    第一阶段:最开始学习的时候,喜欢在设计流程的时候写死人名(即)办理人,这个阶段是入门级。而且你也会觉得这样做非常 so easy(方便、简单)。可是慢慢的,你就会发现,每次需要换人,你就要重新设计流程实例(workflow processInstance),一系列的design->Deployment->start processInstance,从此你再也不觉得so easy 了。

    第二阶段:于是你开始使用了EL表达式变量,这个阶段代表你已经到了提升阶段。可以使用委托类来设置办理人了,是动态的设置哦。但是,你并没有整合自己的权限系统,用的还是Activiti官方的user表和group表,慢慢的,你发现一旦自己的权限系统角色和用户做了调整,那么自己还得去维护这几个表。

    第三阶段:于是,你开始整合自己的权限系统,这个阶段基本是熟练了,可以说是已经完美了。但是这个阶段,每次发送的时候,我们还需要选择一个人去办理他,但是个人觉得,要达到完美状态是不可能的,但是我们还可以自己去做扩展使得它更加的好用,达到我们逾期的目的,(个人观点)。

    第四阶段:其实很多人都会去扩展功能的,源码改造,或者模块扩展。在流程部署的时候就设置好办理人,这样,每次发送的时候,我们并不需要去选择办理人。

    设置办理人色几种方案

    我们先回顾一下,比较传统的动态设置任务办理人的几种方法:

    第一种:在流程设置死,这个感觉无需多说,就是在设计流程的时候,在Assignee里面填写我们的办理人姓名或者相关的ID即可。

     

    第二种:通过委托类(监听类)设置。在流程设计的时候设置监听类,并且在办理人里面设置EL表达式 ${UserId}(随便自己命名)。然后每次办理的时候选择一个办理人。然后传递一个变量过去,然后下一个环节的监听类会设置办理人。

    1   Map<String,Object> map = delegateTask.getVariables();
    2 
    3 delegateTask.setAssignee(map.get("UserId").toString());

    设置办理人可能有三种方案,

    设置办理人的三种方案是有优先级的。

    设置办理人优先级:

    Assignee>Candidate users>Candidate groups。

    设置办理人色几种模式

    第一种:指定办理人模式,即设置办理人,就是设置Assignee。Assignee 受让人; 受托人,代理人; 被指定人;办理人只能指定一个人,不能使用逗号分隔。默认执行签收操作taskService.claim(taskId, currentUserId);在ACT_HI_TASKINST和ACT_RU_TASK会产生数据,这两个表里面的Assignee_字段就是设置的办理人姓名或者对象的ID

    第二种:设置候选用户,候选用户设置办理人不是很多的情况下使用,而且需要签收,也就是说我们常说的抢件模式,Candidate users  候选用户,设置候选组的前提是没有指定Assignee,(即没有执行签收操作)。设置候选组需要主动签taskService.claim(taskId, currentUserId);

    第三种:这只候选组,这个就是这只办理角色或者办理岗位,适合使用在办理人比较多的情况下,而且涉及到几个部门的情形。Candidate groups  候选组

    候选组与候选用户类似,只是要获取候选用户,需要根据候选组找到对应的用户。

    涉及API:

    1 taskService.createTaskQuery().taskAssignee(param);

    根据用户来查询任务(待办任务)

    1 taskService.createTaskQuery().taskCandidateUser(param);  

    根据候选用户查询任务(待签收任务)

    1 taskService.createTaskQuery().taskCandidateGroup(param);

    候选组查询任务(待签收任务)

    1 TaskService().setAssignee(taskId,userId);

    设置办理人 

    1 taskService().addCandidateGroup(taskId, groupid);

    这只候选组,可以添加多个,每次一个addCandidateGroup添加一个

    1 taskService().addCandidateUser(taskId,userid);

    这只候选用户,可以添加多个,每次一个addCandidateUser添加一个

    1 taskService.claim(taskId, currentUserId);

    签收操作。

    扩展实现

    扩展需要添加中间表,我们使用TDD(驱动开发模式)来实现。

    需呀增加一个中间表。

    流程办理人表(act_comm_taskassignee)

    字段

    名称

    是否为空

    备注

    ID

    主键ID

    M

    SID

    节点ID

    M

    assignee

    办理人

    O

    rolegroup

    候选组

    O

    assigneeType

    办理人类型

    M

    1办理人,2为候选人,3为候选组

    activitiname

    节点名称

    O

    建表SQL:

     1 CREATE TABLE `act_comm_taskassignee` (
     2 
     3   `Id` int(11) NOT NULL AUTO_INCREMENT,
     4 
     5   `Sid` varchar(45) NOT NULL,
     6 
     7   `assignee` varchar(45) DEFAULT NULL,
     8 
     9   `rolegroup` varchar(45) DEFAULT NULL,
    10 
    11   `assigneeType` varchar(45) DEFAULT NULL,
    12 
    13   `assigneename` varchar(200) DEFAULT NULL,
    14 
    15   `activitiname` varchar(255) DEFAULT NULL,
    16 
    17   PRIMARY KEY (`Id`),
    18 
    19   UNIQUE KEY `Id_UNIQUE` (`Id`)
    20 
    21 ) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8;

    实体Model:

      1 /**
      2 
      3  *
      4 
      5  */
      6 
      7 package light.mvc.model.workflow;
      8 
      9  
     10 
     11 import javax.persistence.Entity;
     12 
     13 import javax.persistence.Table;
     14 
     15  
     16 
     17 import light.mvc.model.base.IdEntity;
     18 
     19  
     20 
     21 import org.hibernate.annotations.DynamicInsert;
     22 
     23 import org.hibernate.annotations.DynamicUpdate;
     24 
     25  
     26 
     27 /** 
     28 
     29  *  
     30 
     31  * 项目名称:lightmvc 
     32 
     33  * 类名称:FlowAssignee 
     34 
     35  * 类描述: 
     36 
     37  * 创建人:邓家海 
     38 
     39  * 创建时间:2017年8月15日 下午10:01:46 
     40 
     41  * 修改人:deng 
     42 
     43  * 修改时间:2017年8月15日 下午10:01:46 
     44 
     45  * 修改备注: 
     46 
     47  * @version  
     48 
     49  *  
     50 
     51  */
     52 
     53 @Entity
     54 
     55 @Table(name="act_comm_taskassignee")
     56 
     57 @DynamicInsert(true)
     58 
     59 @DynamicUpdate(true)
     60 
     61 public class FlowAssignee extends IdEntity implements java.io.Serializable {
     62 
     63       private String sid;
     64 
     65       /**
     66 
     67        * @return the activitiname
     68 
     69        */
     70 
     71       public String getActivitiname() {
     72 
     73            return activitiname;
     74 
     75       }
     76 
     77  
     78 
     79       /**
     80 
     81        * @param activitiname the activitiname to set
     82 
     83        */
     84 
     85       public void setActivitiname(String activitiname) {
     86 
     87            this.activitiname = activitiname;
     88 
     89       }
     90 
     91  
     92 
     93       private String assignee;
     94 
     95       private String rolegroup;
     96 
     97       private String activitiname;
     98 
     99       private Integer assigneetype;
    100 
    101      
    102 
    103       public FlowAssignee(){
    104 
    105            super();
    106 
    107       }
    108 
    109      
    110 
    111       public FlowAssignee(String sid,String assignee,String rolegroup,Integer assigneetype,String activitiname){
    112 
    113            super();
    114 
    115            this.assignee=assignee;
    116 
    117            this.sid=sid;
    118 
    119            this.rolegroup=rolegroup;
    120 
    121            this.assigneetype=assigneetype;
    122 
    123            this.activitiname=activitiname;
    124 
    125       }
    126 
    127  
    128 
    129       /**
    130 
    131        * @return the sid
    132 
    133        */
    134 
    135       public String getSid() {
    136 
    137            return sid;
    138 
    139       }
    140 
    141  
    142 
    143       /**
    144 
    145        * @param sid the sid to set
    146 
    147        */
    148 
    149       public void setSid(String sid) {
    150 
    151            this.sid = sid;
    152 
    153       }
    154 
    155  
    156 
    157       /**
    158 
    159        * @return the assignee
    160 
    161        */
    162 
    163       public String getAssignee() {
    164 
    165            return assignee;
    166 
    167       }
    168 
    169  
    170 
    171       /**
    172 
    173        * @param assignee the assignee to set
    174 
    175        */
    176 
    177       public void setAssignee(String assignee) {
    178 
    179            this.assignee = assignee;
    180 
    181       }
    182 
    183  
    184 
    185       /**
    186 
    187        * @return the rolegroup
    188 
    189        */
    190 
    191       public String getRolegroup() {
    192 
    193            return rolegroup;
    194 
    195       }
    196 
    197  
    198 
    199       /**
    200 
    201        * @param rolegroup the rolegroup to set
    202 
    203        */
    204 
    205       public void setRolegroup(String rolegroup) {
    206 
    207            this.rolegroup = rolegroup;
    208 
    209       }
    210 
    211  
    212 
    213       /**
    214 
    215        * @return the assigneetype
    216 
    217        */
    218 
    219       public Integer getAssigneetype() {
    220 
    221            return assigneetype;
    222 
    223       }
    224 
    225  
    226 
    227       /**
    228 
    229        * @param assigneetype the assigneetype to set
    230 
    231        */
    232 
    233       public void setAssigneetype(Integer assigneetype) {
    234 
    235            this.assigneetype = assigneetype;
    236 
    237       }
    238 
    239      
    240 
    241 }

    核心实现代码:

    第一步:根据部署ID来查找所有的节点,目的(找到节点ID):

     1 @Test
     2 
     3     public void getDeploymentActivitiIdList(){
     4 
     5         ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
     6 
     7        
     8 
     9         String deploymantId="57577";
    10 
    11                
    12 
    13         ProcessDefinition processDefinition=processEngine.getRepositoryService().createProcessDefinitionQuery().deploymentId(deploymantId).singleResult();
    14 
    15        
    16 
    17         ProcessDefinitionEntity processDefinitionEntity=(ProcessDefinitionEntity)((RepositoryServiceImpl) processEngine
    18 
    19                 .getRepositoryService()).getDeployedProcessDefinition(processDefinition.getId());
    20 
    21        
    22 
    23         List<ActivityImpl> activityList=processDefinitionEntity.getActivities();
    24 
    25        
    26 
    27         for(ActivityImpl activiti:activityList) {
    28 
    29             System.out.println("节点ID:"+activiti.getId());
    30 
    31  
    32 
    33             System.out.println("节点名称:"+activiti.getProperty("name"));
    34 
    35         }
    36 
    37     }

     

     

    第二步,设置办理人,或者候选组,用户:

     1 /**
     2 
     3      * 1.设置办理人,一个节点一个办理人,指定办理人模式,不需要签收,办理人模式
     4 
     5      * 2。设置岗位    1)通过角色,查找权限表,签收模式,角色岗位模式
     6 
     7      *          2)通过节点——>办理人,签收模式,节点(一)-->办理人(多)  ,角色岗位模式
     8 
     9      */
    10 
    11     @Test
    12 
    13     public void setAgneeByActivitiSid(){
    14 
    15         Session session = sessionFactory.openSession();
    16 
    17         String sid="sid-AEC4023A-DEB1-44C8-8784-C3C10F6B484A";   //节点id
    18 
    19         String ActivitiName="总经理";     //节点名称
    20 
    21         FlowAssignee fa=new FlowAssignee(); 
    22 
    23         fa.setActivitiname(ActivitiName);  
    24 
    25         fa.setAssignee("张三");  //办理人
    26 
    27         fa.setAssigneetype(1);  //1是指定办理人,2是指定岗位
    28 
    29         fa.setSid(sid);
    30 
    31         session.save(fa);
    32 
    33    
    34 
    35        
    36 
    37         sid="sid-C8781FAE-02B8-4F8D-9A7D-A8AB4A8CB95A";   //节点id
    38 
    39          ActivitiName="经理";     //节点名称
    40 
    41         fa=new FlowAssignee(); 
    42 
    43         fa.setActivitiname(ActivitiName); 
    44 
    45         fa.setActivitiname(ActivitiName);
    46 
    47         //fa.setAssignee("李四");  //办理人  设置候选组,不能设置办理人
    48 
    49         fa.setRolegroup("产品部");  //办理岗位
    50 
    51         fa.setAssigneetype(1);  //1是指定办理人,2是指定岗位
    52 
    53         fa.setSid(sid);
    54 
    55         session.save(fa);
    56 
    57        
    58 
    59         session.flush();
    60 
    61     }

     

     

    第三步:设置启动流程,并设置第一个环节的办理人:

     1 @Test
     2 
     3     public void SetAgnee(){
     4 
     5         ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
     6 
     7        
     8 
     9         String deploymantId="57577";
    10 
    11         String pid=processEngine.getRepositoryService().createProcessDefinitionQuery().deploymentId(deploymantId)
    12 
    13                 .singleResult().getId();
    14 
    15         ProcessInstance pi = processEngine.getRuntimeService()//与正在执行的流程实例和执行对象相关的service
    16 
    17         .startProcessInstanceById(pid);//使用流程定义的KEY启动流程实例,key对应helloword。bpmn中对应的ID属性值
    18 
    19        
    20 
    21         String pdid=pi.getProcessDefinitionId();
    22 
    23        
    24 
    25         List<Task> taskList=processEngine.getTaskService().createTaskQuery().deploymentId(deploymantId).active().list();
    26 
    27        
    28 
    29         for(Task task:taskList){
    30 
    31              ExecutionEntity execution = (ExecutionEntity)processEngine.getRuntimeService().createExecutionQuery().executionId(task.getExecutionId())
    32 
    33                         .singleResult();
    34 
    35                 String activitiId = execution.getActivityId();
    36 
    37                
    38 
    39                 Session session = sessionFactory.openSession();
    40 
    41              List<FlowAssignee> list=session.createQuery("from FlowAssignee where sid='"+activitiId+"'").list();
    42 
    43  
    44 
    45              if(list.size()>0)
    46 
    47              for(FlowAssignee fa:list){
    48 
    49              if(fa.getAssigneetype()==1){
    50 
    51                    processEngine.getTaskService().setAssignee(task.getId(), fa.getAssignee());
    52 
    53               }else  if(fa.getAssigneetype()==2){
    54 
    55                   processEngine.getTaskService().addCandidateUser(task.getId(), fa.getAssignee());
    56 
    57              }else if(fa.getAssigneetype()==3){
    58 
    59                   processEngine.getTaskService().addCandidateGroup(task.getId(), fa.getRolegroup());
    60 
    61              }           
    62 
    63        
    64 
    65                   
    66 
    67              }      
    68 
    69        
    70 
    71         }
    72 
    73     }

    到这里,我们的就已经完成了根据节点设置办理人的人:

    查询一下:

     1 @Test
     2 
     3     public void getMyTask(){
     4 
     5         ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
     6 
     7         String CandGroup="产品部";
     8 
     9         Task task=processEngine.getTaskService().createTaskQuery().taskCandidateGroup(CandGroup).active().singleResult();
    10 
    11         List<IdentityLink> ilList=processEngine.getTaskService().getIdentityLinksForTask(task.getId());
    12 
    13         System.out.println("办理人:"+task.getAssignee());
    14 
    15         System.out.println("任务ID:"+task.getId());
    16 
    17         System.out.println("任务ID:"+task.getName());
    18 
    19         for(IdentityLink i:ilList){
    20 
    21             System.out.println("组ID:"+i.getGroupId());
    22 
    23             System.out.println("用户:"+i.getUserId());
    24 
    25         }
    26 
    27  
    28 
    29     }

     

    结果是正确的。

    注意:

    设置办理人、候选人、候选组,三个是有有优先级的,不能同时设置,同时设置等价于执行了签收操作。

    扩展是要求对Activiti基础有一定的功底的,如果不是很熟悉,请先使用委托类或者直接设置办理人

    本文主要实现了核心功能,整合到系统功能暂时还没实现。但是有基础的人看完本文就会知道怎么进行扩展。

     Activiti交流QQ群:634320089

  • 相关阅读:
    编译原理实验之SLR1文法分析
    机器学习中的特征选择filter
    按部就班的吴恩达机器学习网课用于讨论(4)
    Linux客户端网口输入转串口输出
    按部就班的吴恩达机器学习网课用于讨论(3)
    关于网络手动搭建的一点补充说明
    按部就班的吴恩达机器学习网课用于讨论(2)
    按部就班的吴恩达机器学习网课用于讨论(1)
    java学习与应用(5.3)--Spring
    java学习与应用(5.2)--Spring Boot 预告篇
  • 原文地址:https://www.cnblogs.com/dengjiahai/p/7536999.html
Copyright © 2020-2023  润新知