关于workflow:Flowable-设置任务处理人的四种方式

5次阅读

共计 6904 个字符,预计需要花费 18 分钟才能阅读完成。

@[toc]
上篇文章松哥和大家分享了 Flowable 中的 ReceiveTask,这只是流程中工作的一种,明天咱们就一起来看另外一个更为常见的 Task–UserTask。

UserTask 看名字就晓得,须要人工干预,而人工解决的形式有很多种,咱们能够设置节点是由哪个用户解决,也能够设置是由哪个用户组来解决(相当于是由哪个角色来解决),明天这篇文章我次要和大家分享设置用户的三种形式,至于如何设置用户组,这个咱们下篇文章再聊。

当初,假如我有如下一个简略的流程图:

那么我该如何设置这个用户节点的解决人呢?

1. 指定具体用户

第一种形式,是咱们在绘制流程图的时候,能够选中这个节点,而后间接设置流程的解决人,像上面这样:

而后在关上的窗口中抉择固定值,设置具体调配的用户是 javaboy,如下图:

好了,当初这个节点就固定的由一个名为 javaboy 的用户去解决了。

对应的 XML 文件如下:

<process id="demo01" name="demo01" isExecutable="true">
  <documentation>demo01</documentation>
  <startEvent id="startEvent1" flowable:formFieldValidation="true"></startEvent>
  <userTask id="sid-5F901234-AFF1-480E-9D66-2D196B910BA3" flowable:assignee="javaboy" flowable:formFieldValidation="true">
    <extensionElements>
      <modeler:initiator-can-complete xmlns:modeler="http://flowable.org/modeler"><![CDATA[false]]></modeler:initiator-can-complete>
    </extensionElements>
  </userTask>
  <sequenceFlow id="sid-71FB3A81-F753-419D-9A0A-2FC6E5361CED" sourceRef="startEvent1" targetRef="sid-5F901234-AFF1-480E-9D66-2D196B910BA3"></sequenceFlow>
  <endEvent id="sid-D0B9E5BF-8C1A-4F8F-B2C2-F423F5DC556D"></endEvent>
  <sequenceFlow id="sid-DEBE03CD-F247-4EF3-BB67-ABBA94739B0A" sourceRef="sid-5F901234-AFF1-480E-9D66-2D196B910BA3" targetRef="sid-D0B9E5BF-8C1A-4F8F-B2C2-F423F5DC556D"></sequenceFlow>
</process>

在下面这段 XML 中,小伙伴们看到 UserTask 节点中有一个 flowable:assignee="javaboy",这句话就是设置这个 UserTask 的解决人。

接下来,咱们部署并启动这个流程(具体的部署启动形式能够参考本系列之前的文章),启动之后,咱们能够在数据库的 ACT_RU_TASK 表中看到,这个 UserTask 的解决人是 javaboy,如下图:

当初咱们能够通过 Java 代码去查问 javaboy 须要解决的 UserTask 了,如下:

@Autowired
TaskService taskService;
@Test
void test11() {List<Task> list = taskService.createTaskQuery().taskAssignee("javaboy").list();
    for (Task task : list) {logger.info("id:{},name:{}",task.getId(),task.getName());
    }
}

这个查问,实质上其实就是去 ACT_RU_TASK 表中查问的,咱们来看看执行的 SQL:

查问到这个工作之后,javaboy 有两种抉择:

  1. 将这个工作指定给另外一个人,例如 zhangsan。
  2. 本人解决。

1.1 从新指定工作解决人

假如 javaboy 查问到本人的工作之后,想把这个工作交给 zhangsan 去解决,形式如下:

@Autowired
TaskService taskService;
@Test
void test11() {List<Task> list = taskService.createTaskQuery().taskAssignee("javaboy").list();
    for (Task task : list) {taskService.setAssignee(task.getId(),"zhangsan");
    }
}

这行代码执行实现后,咱们看数据库中的 ACT_RU_TASK 表,还是方才那条记录,然而解决人变了,变成了 zhangsan:

小伙伴们看到,版本号从 1 变为 2 了,阐明这条记录被更新过了,解决人则从 javaboy 变为了 zhangsan。

最初咱们再来看下这个操作所执行的 SQL,来验证一下咱们后面的论断:

小伙伴们留神看这里执行的 SQL,以及对应的参数,阐明咱们下面的剖析是没有问题的。

1.2 本人解决

如果 javaboy 想本人解决这个工作也是能够的,形式如下:

@Autowired
TaskService taskService;
@Test
void test11() {List<Task> list = taskService.createTaskQuery().taskAssignee("javaboy").list();
    for (Task task : list) {taskService.complete(task.getId());
    }
}

解决实现后,ACT_RU_TASK 表中的记录也会被主动删除掉(执行过的 UserTask 会被主动删除)。

这种形式是指定了具体的用户,很显然这种硬编码的形式应用起来很不不便,咱们须要的是可能动静指定工作解决人的形式。

2. 通过变量设置

如果想动静指定 UserTask 的解决人,则能够通过变量来实现,具体形式如下:

在绘制流程图的时候,还是指定流程的具体解决人,然而在指定的时候,应用变量代替,如下图:

这里的 #{manager} 示意这个 UserTask 由一个名为 manager 的变量来指定,此时的 XML 文件则是上面这样:

<process id="demo01" name="demo01" isExecutable="true">
  <documentation>demo01</documentation>
  <startEvent id="startEvent1" flowable:formFieldValidation="true"></startEvent>
  <userTask id="sid-5F901234-AFF1-480E-9D66-2D196B910BA3" flowable:assignee="#{manager}" flowable:formFieldValidation="true">
    <extensionElements>
      <modeler:initiator-can-complete xmlns:modeler="http://flowable.org/modeler"><![CDATA[false]]></modeler:initiator-can-complete>
    </extensionElements>
  </userTask>
  <sequenceFlow id="sid-71FB3A81-F753-419D-9A0A-2FC6E5361CED" sourceRef="startEvent1" targetRef="sid-5F901234-AFF1-480E-9D66-2D196B910BA3"></sequenceFlow>
  <endEvent id="sid-D0B9E5BF-8C1A-4F8F-B2C2-F423F5DC556D"></endEvent>
  <sequenceFlow id="sid-DEBE03CD-F247-4EF3-BB67-ABBA94739B0A" sourceRef="sid-5F901234-AFF1-480E-9D66-2D196B910BA3" targetRef="sid-D0B9E5BF-8C1A-4F8F-B2C2-F423F5DC556D"></sequenceFlow>
</process>

小伙伴们看到,UserTask 节点中的 flowable:assignee="#{manager}" 就示意这个 UserTask 的解决人由 manager 变量指定。

对于这样的流程,咱们在上一个节点处就须要指定下一个节点的解决人,对于以后案例来说,当然是要在流程启动的时候,指定这个 UserTask 的解决人,形式如下:

@Test
void test01() {Map<String, Object> variables = new HashMap<>();
    variables.put("manager", "javaboy");
    ProcessInstance pi = runtimeService.startProcessInstanceByKey("demo01",variables);
    logger.info("id:{},activityId:{}", pi.getId(), pi.getActivityId());
}

当流程启动胜利之后,大家去查看 ACT_RU_TASK 表,就能够看到,有一个待处理的 UserTask,解决人是 javaboy,如下图:

能看到这条记录,就阐明这个 UserTask 的解决人咱们曾经设置胜利了。

接下来具体的解决逻辑,则参考 1.1 和 1.2 大节。

3. 通过监听器设置

当然,咱们也能够通过监听器来设置工作的解决人。具体形式如下:

首先咱们在绘制流程图的时候,不须要给 UserTask 调配用户,如下图:

而后咱们为这个 UserTask 设置一个工作监听器,步骤如下:

首先点击 + 号,而后抉择 CREATE 事件,最初再给出事件对应的实体类,如下:

当然这个实体类是咱们我的项目中实在存在的一个类,如下:

public class MyTaskListener implements TaskListener {
    @Override
    public void notify(DelegateTask delegateTask) {delegateTask.setAssignee("javaboy");
    }
}

当这个 UserTask 创立的时候,就会触发这个监听器,为该 UserTask 设置解决人。

咱们来看看这个流程图对应的 XML 文件是什么样子的:

<process id="demo01" name="demo01" isExecutable="true">
  <documentation>demo01</documentation>
  <startEvent id="startEvent1" flowable:formFieldValidation="true"></startEvent>
  <userTask id="sid-5F901234-AFF1-480E-9D66-2D196B910BA3" flowable:formFieldValidation="true">
    <extensionElements>
      <flowable:taskListener event="create" class="org.javaboy.flowableidm.MyTaskListener"></flowable:taskListener>
    </extensionElements>
  </userTask>
  <sequenceFlow id="sid-71FB3A81-F753-419D-9A0A-2FC6E5361CED" sourceRef="startEvent1" targetRef="sid-5F901234-AFF1-480E-9D66-2D196B910BA3"></sequenceFlow>
  <endEvent id="sid-D0B9E5BF-8C1A-4F8F-B2C2-F423F5DC556D"></endEvent>
  <sequenceFlow id="sid-DEBE03CD-F247-4EF3-BB67-ABBA94739B0A" sourceRef="sid-5F901234-AFF1-480E-9D66-2D196B910BA3" targetRef="sid-D0B9E5BF-8C1A-4F8F-B2C2-F423F5DC556D"></sequenceFlow>
</process>

小伙伴们看到,event="create" class="org.javaboy.flowableidm.MyTaskListener" 就是咱们设置的内容了。

当初咱们部署并启动这个流程,当咱们流程启动后,就能够在 ACT_RU_TASK 表中看到一条 javaboy 待处理的工作了。

4. 其余状况

最初再来说说一种非凡状况,就是这个 UserTask 由工作的发起人解决,工作是谁发动的,谁来解决人这个 UserTask。

这个首先须要在流程启动事件上设置工作的发起人变量名,如下,流程的启动节点,而后设置工作的发起人:

接下来,在给 UserTask 设置解决人的时候,设置解决人和工作的发起人的变量是同一个,如下图:

好啦,这就能够了。来看看对应的 XML 文件:

<process id="demo01" name="demo01" isExecutable="true">
  <documentation>demo01</documentation>
  <startEvent id="startEvent1" flowable:initiator="INITATOR" flowable:formFieldValidation="true"></startEvent>
  <userTask id="sid-5F901234-AFF1-480E-9D66-2D196B910BA3" flowable:assignee="#{INITATOR}" flowable:formFieldValidation="true">
    <extensionElements>
      <modeler:initiator-can-complete xmlns:modeler="http://flowable.org/modeler"><![CDATA[false]]></modeler:initiator-can-complete>
    </extensionElements>
  </userTask>
  <sequenceFlow id="sid-71FB3A81-F753-419D-9A0A-2FC6E5361CED" sourceRef="startEvent1" targetRef="sid-5F901234-AFF1-480E-9D66-2D196B910BA3"></sequenceFlow>
  <endEvent id="sid-D0B9E5BF-8C1A-4F8F-B2C2-F423F5DC556D"></endEvent>
  <sequenceFlow id="sid-DEBE03CD-F247-4EF3-BB67-ABBA94739B0A" sourceRef="sid-5F901234-AFF1-480E-9D66-2D196B910BA3" targetRef="sid-D0B9E5BF-8C1A-4F8F-B2C2-F423F5DC556D"></sequenceFlow>
</process>

startEvent 中有一个 flowable:initiator="INITATOR" 示意设置流程发起人的变量为 INITATOR。后续在 UserTask 中应用该变量即可。

将这个流程部署胜利之后,依照如下形式启动流程:

@Test
void test01() {Authentication.setAuthenticatedUserId("javaboy");
    ProcessInstance pi = runtimeService.startProcessInstanceByKey("demo01");
    logger.info("id:{},activityId:{}", pi.getId(), pi.getActivityId());
}

Authentication.setAuthenticatedUserId("javaboy"); 示意设置流程的发起人为 javaboy。

好啦,明天的文章就和小伙伴们介绍了如何给 UserTask 设置解决人,前面松哥再和大家分享如何给 UserTask 设置候选人和候选组。

正文完
 0