java基础

工作流面试重点内容!如何控制工作流流程?使用流程任务控制工作执行

2021-04-24  本文已影响0人  攻城狮Chova

任务

用户任务

描述
图形标记
XML内容
<userTask id="theTask" name="Important task" />
<userTask id="theTask" name="Schedule meeting" >
  <documentation>
          Schedule an engineering meeting for next week with the new hire.
  </documentation>
task.getDescription()
持续时间
<userTask id="theTask" name="Important task" activiti:dueDate="${dateVariable}"/>
用户分配
<process ... >

  ...

  <userTask id='theTask' name='important task' >
    <humanPerformer>
      <resourceAssignmentExpression>
        <formalExpression>kermit</formalExpression>
      </resourceAssignmentExpression>
    </humanPerformer>
  </userTask>
List<Task> tasks = taskService.createTaskQuery().taskAssignee("kermit").list();
<process ... >

  ...

  <userTask id='theTask' name='important task' >
    <potentialOwner>
      <resourceAssignmentExpression>
        <formalExpression>user(kermit), group(management)</formalExpression>
      </resourceAssignmentExpression>
    </potentialOwner>
  </userTask>
List<Task> tasks = taskService.createTaskQuery().taskCandidateUser("kermit");

这会获取所有kermit为候选人的任务,表达式中包含user(kermit).这也会获得所有分配包含kermit这个成员的群组(比如,group(management),前提是kermit是这个组的成员,并且使用了activiti的账号组件).用户所在的群组是在运行阶段获取的, 它们可以通过IdentityService进行管理

<formalExpression>accountancy</formalExpression>
Activiti对任务分配的扩展
<userTask id="theTask" name="my task" activiti:assignee="kermit" />
<userTask id="theTask" name="my task" activiti:candidateUsers="kermit, gonzo" />
<userTask id="theTask" name="my task" activiti:candidateGroups="management, accountancy" />
<userTask id="task1" name="My task" >
  <extensionElements>
    <activiti:taskListener event="create" class="org.activiti.MyAssignmentHandler" />
  </extensionElements>
</userTask>
public class MyAssignmentHandler implements TaskListener {

  public void notify(DelegateTask delegateTask) {
    // Execute custom identity lookups here

    // and then for example call following methods:
    delegateTask.setAssignee("kermit");
    delegateTask.addCandidateUser("fozzie");
    delegateTask.addCandidateGroup("management");
    ...
  }

}
<userTask id="task" name="My Task" activiti:assignee="${ldapService.findManagerForEmployee(emp)}"/>
<userTask id="task" name="My Task" activiti:candidateUsers="${ldapService.findAllSales()}"/>
public class FakeLdapService {

  public String findManagerForEmployee(String employee) {
    return "Kermit The Frog";
  }

  public List<String> findAllSales() {
    return Arrays.asList("kermit", "gonzo", "fozzie");
  }

}

脚本任务

描述
图形标记
XML内容
<scriptTask id="theScriptTask" name="Execute script" scriptFormat="groovy">
  <script>
    sum = 0
    for ( i in inputArray ) {
      sum += i
    }
  </script>
</scriptTask>

scriptFormat的值必须兼容JSR-223(java平台的脚本语言).默认Javascript会包含在JDK中,不需要额外的依赖.如果要使用其他的脚本引擎,必须要是JSR-223引擎兼容的.还需要把对应的jar添加到classpath下, 并使用合适的名称:activiti单元测试经常使用groovy

<dependency>
      <groupId>org.codehaus.groovy</groupId>
      <artifactId>groovy-all</artifactId>
      <version>2.x.x<version>
</dependency>
脚本变量
<script>
    sum = 0
    for ( i in inputArray ) {
      sum += i
    }
</script>
<scriptTask id="script" scriptFormat="JavaScript" activiti:autoStoreVariables="false">

参数默认为false: 如果没有为脚本任务定义设置参数,所有声明的变量将只存在于脚本执行的阶段

<script>
    def scriptVar = "test123"
    execution.setVariable("myVar", scriptVar)
</script>
脚本结果
<scriptTask id="theScriptTask" name="Execute script" scriptFormat="juel" activiti:resultVariable="myVar">
  <script>#{echo}</script>
</scriptTask>

脚本的结果-表达式 #{echo} 的值会在脚本完成后,设置到myVar变量中

Java服务任务

描述
图形标记
XML内容
<serviceTask id="javaService"
             name="My Java Service Task"
             activiti:class="org.activiti.MyJavaDelegate" />
<serviceTask id="serviceTask" activiti:delegateExpression="${delegateExpressionBean}" />

delegateExpressionBean是一个实现了JavaDelegate接口的bean,定义在实例的spring容器中
要执行指定的UEL方法表达式, 需要使用activiti:expression:

<serviceTask id="javaService"
             name="My Java Service Task"
             activiti:expression="#{printer.printMessage()}" />

方法printMessage()会调用名为printer对象的方法

<serviceTask id="javaService"
             name="My Java Service Task"
             activiti:expression="#{printer.printMessage(execution, myVar)}" />

调用名为printer对象上的方法printMessage.第一个参数是DelegateExecution, 在表达式环境中默认名称为execution. 第二个参数传递的是当前流程的名为myVar的变量
要执行指定的UEL方法表达式, 需要使用activiti:expression:

<serviceTask id="javaService"
             name="My Java Service Task"
             activiti:expression="#{split.ready}" />

ready属性的getter方法:getReady() 会作用于名为split的bean上.这个对象会被解析为流程对象spring环境中的对象

实现
public class ToUppercase implements JavaDelegate {

  public void execute(DelegateExecution execution) throws Exception {
    String var = (String) execution.getVariable("input");
    var = var.toUpperCase();
    execution.setVariable("input", var);
  }

}
属性注入
<serviceTask id="javaService"
    name="Java service invocation"
    activiti:class="org.activiti.examples.bpmn.servicetask.ToUpperCaseFieldInjected">
    <extensionElements>
      <activiti:field name="text" stringValue="Hello World" />
  </extensionElements>
</serviceTask>

ToUpperCaseFieldInjected类有一个text属性,类型是org.activiti.engine.delegate.Expression. 调用text.getValue(execution) 时,会返回定义的字符串Hello World

<serviceTask id="javaService"
    name="Java service invocation"
    activiti:class="org.activiti.examples.bpmn.servicetask.ToUpperCaseFieldInjected">
  <extensionElements>
    <activiti:field name="text">
        <activiti:string>
          Hello World
      </activiti:string>
    </activiti:field>
  </extensionElements>
</serviceTask>
<serviceTask id="javaService" name="Java service invocation"
  activiti:class="org.activiti.examples.bpmn.servicetask.ReverseStringsFieldInjected">

  <extensionElements>
    <activiti:field name="text1">
      <activiti:expression>${genderBean.getGenderString(gender)}</activiti:expression>
    </activiti:field>
    <activiti:field name="text2">
       <activiti:expression>Hello ${gender == 'male' ? 'Mr.' : 'Mrs.'} ${name}</activiti:expression>
    </activiti:field>
  </ extensionElements>
</ serviceTask>
public class ReverseStringsFieldInjected implements JavaDelegate {

  private Expression text1;
  private Expression text2;

  public void execute(DelegateExecution execution) {
    String value1 = (String) text1.getValue(execution);
    execution.setVariable("var1", new StringBuffer(value1).reverse().toString());

    String value2 = (String) text2.getValue(execution);
    execution.setVariable("var2", new StringBuffer(value2).reverse().toString());
  }
}
服务任务结果
<serviceTask id="aMethodExpressionServiceTask"
    activiti:expression="#{myService.doSomething()}"
    activiti:resultVariable="myVar" />

服务流程的返回值(在myService上调用doSomething() 方法的返回值,myService可能是流程变量,也可能是spring的bean),在服务执行完成之后,会设置到名为myVar的流程变量里

处理异常

执行自定义逻辑时,常常需要捕获对应的业务异常,在流程内部进行处理

public class ThrowBpmnErrorDelegate implements JavaDelegate {

  public void execute(DelegateExecution execution) throws Exception {
    try {
      executeBusinessLogic();
    } catch (BusinessException e) {
      throw new BpmnError("BusinessExceptionOccured");
    }
  }

}

构造参数是错误代码,会被用来决定哪个错误处理器会来响应这个错误
这个机制只用于业务失败,应该被流程定义中设置的边界错误事件或错误事件子流程处理. 技术上的错误应该使用其他异常类型,通常不会在流程里处理

<serviceTask id="javaService"
  name="Java service invocation"
  activiti:class="org.activiti.ThrowsExceptionBehavior">
</serviceTask>

<sequenceFlow id="no-exception" sourceRef="javaService" targetRef="theEnd" />
<sequenceFlow id="exception" sourceRef="javaService" targetRef="fixException" />

这里的服务任务有两个外出顺序流:分别叫exceptionno-exception. 异常出现时会使用顺序流的ID来决定流向

public class ThrowsExceptionBehavior implements ActivityBehavior {

  public void execute(ActivityExecution execution) throws Exception {
    String var = (String) execution.getVariable("var");

    PvmTransition transition = null;
    try {
      executeLogic(var);
      transition = execution.getActivity().findOutgoingTransition("no-exception");
    } catch (Exception e) {
      transition = execution.getActivity().findOutgoingTransition("exception");
    }
    execution.take(transition);
  }

}
JavaDelegate使用Activiti服务
public class StartProcessInstanceTestDelegate implements JavaDelegate {

  public void execute(DelegateExecution execution) throws Exception {
    RuntimeService runtimeService = execution.getEngineServices().getRuntimeService();
    runtimeService.startProcessInstanceByKey("myProcess");
  }

}
@Component("startProcessInstanceDelegate")
public class StartProcessInstanceTestDelegateWithInjection {

    @Autowired
    private RuntimeService runtimeService;

    public void startProcess() {
      runtimeService.startProcessInstanceByKey("oneTaskProcess");
    }

}
上一篇 下一篇

猜你喜欢

热点阅读