开发者

解读Camunda中强大的监听服务

目录
  • 简介
  • 创建工程
  • JavaDelegate
  • TaskListener
  • ExecutionListener
  • 部署发起流程
    • CustomExecutionListener开始节点
    • CustomExecutionListener
    • CustomJavaDelegate
    • CustomExecutionListener
    • CustomTaskListener用户节点
  • Expression
    • Delegate Expression
      • 流程图
        • 总结

          简介

          Camunda预览了很多接口,以便于我们扩展,其中最重要的莫过于各种监听接口,本文就将接受三个最终常用的接口:

          1. ExecutionListener
          2. JavaDelegate
          3. TaskListener

          并介绍下面3个ListenerType的区别:

          1. Java Class
          2. Expression
          3. Delegate expression

          创建工程

          我们还是使用SpringBoot来创建工程,可以通过下面链接生成一个集成Camunda的SpringBoot工程

          SpringBoot Camunda工程生成

          也可以直接拷贝下面的pom自己创建:

          <project XMLns="http://maven.apache.org/POM/4.0.0"
                   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                   xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
          
            <modelVersion>4.0.0</modelVersion>
          
            <groupId>com.example.workflow</groupId>
            <artifactId>my-project</artifactId>
            <version>1.0.0-SNAPSHOT</version>
          
            <properties>
              <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
              <maven.compiler.source>17</maven.compiler.source>
              <maven.compiler.target>17</maven.compiler.target>
            </properties>
          
            <dependencyManagement>
              <dependencies>
                <dependency>
                  <groupId>org.springframework.boot</groupId>
                  <artifactId>spring-boot-dependencjsies</artifactId>
                  <version>3.1.1</version>
                  <type>pom</type>
                  <scope>import</scope>
                </dependency>
          
                <dependency>
                  <groupId>org.camunda.bpm</groupId>
                  <artifactId>camunda-bom</artifactId>
                  <version>7.20.0</version>
                  <scope>import</scope>
                  <type>pom</type>
                </dependency>
              </dependencies>
            </dependencyManagement>
          
            <dependencies>
              <dependency>
                <groupId>org.camunda.bpm.springboot</groupId>
                <artifactId>camunda-bpm-spring-boot-starter-rest</artifactId>
              </dependency>
          
              <dependency>
                <groupId>org.camunda.bpm.springboot</groupId>
                <artifactId>camunda-bpm-spring-boot-starter-webapp</artifactId>
              </dependency>
          
              <dependency>
                <groupId>org.camunda.bpm</groupId>
                <artifactId>camunda-engine-plugin-spin</artifactId>
              </dependency>
          
              <dependency>
                <groupId>org.camunda.spin</groupId>
                <artifactId>camunda-spin-dataformat-all</artifactId>
              </dependency>
          
              <dependency>
                <groupId>com.h2database</groupId>
                <artifactId>h2</artifactId>
              </dependency>
          
              <dependency>
                <groupId>com.mysql</groupId>
                <artifactId>mysql-connector-j</artifactId>
              </dependency>
          
              <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-jdbc</artifactId>
              </dependency>
          
            </dependencies>
          
            <build>
              <plugins>
                <plugin>
                  <groupId>org.springframework.boot</groupId>
                  <artifactId>spring-boot-maven-plugin</artifactId>
                  <version>3js.1.1</version>
                </plugin>
              </plugins>
            </build>
          
          </project>
          

          如果不想使用默认的H2数据库,可以参考下面修改配置文件:application.yaml

          #spring.datasource.url: jdbc:h2:file:./camunda-h2-database
          
          camunda.bpm.admin-user:
            id: demo
            password: demo
          
          #camunda.bpm.database:
          #  schema-update: drop-create
          
          spring.datasource:
            url: jdbc:mysql://127.0.0.1:3306/clearn?characterEncoding=UTF-8&useUnicode=true&useSSL=false&zeroDateTimeBehavior=convertToNull&serverTimezone=Asia/Shanghai
            driver-class-name: com.mysql.cj.jdbc.Driver
            username: tim
            password: pd
          

          两点需要注意:

          1. 需要添加相关数据库驱动lib
          2. camunda.bpm.database.schema-update好像不生效,需要手动创建一下Camunda相关表

          自己测试,如果怕麻烦,直接使用默认的H2数据库即可。

          然后就可以直接启动了:

          @SpringBootApplication
          public class Applicati编程客栈on {
          
            public static void main(String... args) {
              SpringApplication.run(Application.class, args);
            }
          
          }
          

          JavaDelegate

          对于Camunda的服务节点,我们可以绑定一个Java类,这个Java类只需要实现org.camunda.bpm.engine.delegate.JavaDelegate接口即可。

          • Type选Java Class:

          解读Camunda中强大的监听服务

          import org.camunda.bpm.engine.delegate.DelegateExecution;
          import org.camunda.bpm.engine.delegate.JavaDelegate;
          
          public class CustomJavaDelegate implements JavaDelegate {
          
              @Override
              public void execute(DelegateExecution delegateExecution) throws Exception {
                  System.out.println(CustomJavaDelegate.class.getName() + "--start");
                  System.out.println("getProcessInstanceId:" + delegateExecution.getProcessInstanceId());
                  System.out.println("getActivityInstanceId:" + delegateExecution.getActivityInstanceId());
                  System.out.println("getCurrentActivityId:" + delegateExecution.getCurrentActivityId());
                  System.out.println("getCurrentActivityName:" + delegateExecution.getCurrentActivityName());
                  System.out.println("getProcessBusinessKey:" + delegateExecution.getProcessBusinessKey());
                  System.out.println("getProcessDefinitionId:" + delegateExecution.getProcessDefinitionId());
                  System.out.println("getBusinessKey:" + delegateExecution.getBusinessKey());
                  System.out.println("getEventName:" + delegateExecution.getEventName());
                  Double paramA = (Double) delegateExecution.getVariable("paramA");
                  String paramB = (String) delegateExecution.getVariable("paramB");
                  System.out.println(paramA);
                  System.out.println(paramB);
                  delegateExecution.setVariable("CustomJavaDelegateP1","p1");
                  delegateExecution.setVariable("CustomJavaDelegateP2",500);
                  System.out.println(CustomJavaDelegate.class.getName() + "--end");
              }
          }
          

          TaskListener

          对于用户节点,我们可以配置TaskListener,来监听用户节点的一些事件,如:

          1. create
          2. assignment
          3. delete
          4. complete
          5. update
          6. timeout

          解读Camunda中强大的监听服务

          import org.camunda.bpm.engine.delegate.DelegateTask;
          import org.camunda.bpm.engine.delegate.TaskListener;
          
          public class CustomTaskListener implements TaskListener {
          
              @Override
              public void notify(DelegateTask delegateTask) {
                  System.out.println(CustomTaskListener.class.getName() + "--start");
                  System.out.println("processInstanceId:" + delegateTask.getProcessInstanceId());
                  System.out.println("getAssignee:" + delegateTask.getAssignee());
                  System.out.println("getId:" + delegateTask.getId());
                  System.out.println("getName:" + delegateTask.getName());
                  System.out.println("getEventName:" + delegateTask.getEventName());
                  System.out.println("getPriority:" + delegateTask.getPriority());
                  System.out.println("getCaseDefinitionId:" + delegateTask.getCaseDefinitionId());
                  System.out.println("getCaseExecutionId:" + delegateTask.getCaseExecutionId());
                  System.out.println("getDueDate:" + delegateTask.getDueDate());
                  System.out.println("getTaskDefinitionKey:" + delegateTask.getTaskDefinitionKey());
                  System.out.println("getOwner:" + delegateTask.getOwner());
                  System.out.println("getDescription:" + delegateTask.getDescription());
                  System.out.println(CustomTaskListener.class.getName() + "--end");
              }
          }
          

          ExecutionListener

          基本所有节点都可以配置Execution listener:

          解读Camunda中强大的监听服务

          import org.camunda.bpm.en编程客栈gine.RuntimeService;
          import org.camunda.bpm.engine.delegate.DelegateExecution;
          import org.camunda.bpm.engine.delegate.ExecutionListener;
          
          
          public class CustomExecutionListener implements ExecutionListener {
          
              @Override
              public void notify(DelegateExecution delegateExecution) throws Exception {
                  System.out.println(CustomExecutionListener.class.getName() + "--start");
                  System.out.println("getProcessInstanceId:" + delegateExecution.getProcessInstanceId());
                  System.out.println("getProcessDefinitionId:" + delegateExecution.getProcessDefinitionId());
                  System.out.println("getActivityInstanceId:" + delegateExecution.getActivityInstanceId());
                  System.out.println("getCurrentActivityId:" + delegateExecution.getCurrentActivityId());
                  System.out.println("getCurrentActivityName:" + delegateExecution.getCurrentActivityName());
                  System.out.println("getProcessBusinessKey:" + delegateExecution.getProcessBusinessKey());
                  System.out.println("getBusinessKey:" + delegateExecution.getBusinessKey());
                  // 获取参数
                  delegateExecution.getVariable("paramA");
                  // 设置参数
                  delegateExecution.setVariable("paramZ","paramZValue");
                  // 可以获取ProcessEngine、RuntimeService来执行更多的操作
                  RuntimeService runtimeService = delegateExecution.getProcessEngine().getRuntimeService();
                  System.out.println(runtimeService);
                  System.out.println(CustomExecutionListener.class.getName() + "--end");
              }
          }
          

          部署发起流程

          解读Camunda中强大的监听服务

          解读Camunda中强大的监听服务

          解读Camunda中强大的监听服务

          CustomExecutionListener开始节点

          com.example.workflow.delegate.CustomExecutionListener--start
          getProcessInstanceId:646f4f07-bf4c-11ee-a70e-00ffe7687986
          getProcessDefinitionId:Process_1dnzxeh:3:830657fb-bf4a-11ee-b1f6-00ffe7687986
          getActivityInstanceId:null
          getCurrentActivityId:StartEvent_1
          getCurrentActivityName:null
          getProcessBusinessKey:listener-30
          getBusinessKey:listener-30
          org.camunda.bpm.engine.impl.RuntimeServiceImpl@1d380352
          com.example.workflow.delegate.CustomExecutionListener--end
          

          CustomExecutionListener

          com.example.workflow.delegate.CustomExecutionListener--start
          getProcessInstanceId:646f4f07-bf4c-11ee-a70e-00ffe7687986
          getProcessDefinitionId:Process_1dnzxeh:3:830657fb-bf4a-11ee-b1f6-00ffe7687986
          getActivityInstanceId:StartEvent_1:64747f30-bf4c-11ee-a70e-00ffe7687986
          getCurrentActivityId:StartEvent_1
          getCurrentActivityName:null
          getProcessBusinessKey:listener-30
          getBusinessKey:listener-30
          org.camunda.bpm.engine.impl.RuntimeServiceImpl@1d380352
          com.example.workflow.delegate.CustomExecutionListener--end
          

          CustomJavaDelegate

          com.example.workflow.delegate.CustomJavaDelegate--start
          getProcessInstanceId:646f4f07-bf4c-11ee-a70e-00ffe7687986
          getActivityInstanceId:Activity_1claer7:6475dec2-bf4c-11ee-a70e-00ffe7687986
          getCurrentActivityId:Activity_1claer7
          getCurrentActivityName:bzService
          getProcessBusinessKey:listener-30
          getProcessDefinitionId:Process_1dnzxeh:3:830657fb-bf4a-11ee-b1f6-00ffe7687986
          getBusinessKey:listener-30
          getEventName:null
          3.14
          haha
          com.example.workflow.delegate.CustomJavaDelegate--end
          

          CustomExecutionListener

          com.example.workflow.delegate.CustomExecutionListener--start
          getProcessInstanceId:646f4f07-bf4c-11ee-a70e-00ffe7687986
          getProcessDefinitionId:Process_1dnzxeh:3:830657fb-bf4a-11ee-b1f6-00ffe7687986
          getActivityInstanceId:Activity_1xjraoy:6476c927-bf4c-11ee-a70e-00ffe7687986
          getCurrentActivityId:Activity_1xjraoy
          getCurrentActivityName:userTask
          getProcessBusinessKey:listener-30
          getBusinessKey:listener-30
          org.camunda.bpm.engine.impl.RuntimeServiceImpl@1d380352
          com.example.workflow.delegate.CustomExecutionListener--end
          

          CustomTaskListener用户节点

          com.example.workflow.delegate.CustomTaskListener--start
          processInstanceId:646f4f07-bf4c-11ee-a70e-00ffe7687986
          getAssignee:null
          getId:64771749-bf4c-11ee-a70e-00ffe7687986
          getName:userTask
          getEventName:create
          getPriority:50
          getCaseDefinitionId:null
          getCaseExecutionId:null
          getDueDate:null
          getTaskDefinitionKey:Activity_1xjraoy
          getOwner:null
          getDescription:null
          com.example.workflow.delegate.CustomTaskListener--end
          

          Expression

          Expression的优势在于不用继承特别的类,就可以调用相关方法。

          注意:需要将类注入容器

          import org.camunda.bpm.engine.delegate.DelegateExecution;
          import org.springframework.stereotype.Component;
          
          /**
           * #{expressionDelegateExecution.exe(execution)}
           */
          @Component("expressionDelegateExecution")
          public class ExpressionDelegateExecution {
          
              public void exe(DelegateExecution execution){
                  String processInstanceId = execution.getProcessInstanceId();
                  System.out.println("ExpressionDelegateExecution:" + processInstanceId);
              }
          }
          

          解读Camunda中强大的监听服务

          表达式中的execution是内置变量,Camunda会自动注入一个DelegateExecution实例,还有一个常用的内置变量task,Camunda会自动注入一个DelegateTask实例。

          Delegate Expression

          Delegate Expression可以看做是加强版的Expression。

          它最大的一个特点是对于实现了:

          1. ExecutionListener
          2. JavaDelegate
          3. TaskListener

          上面的类,Delegate Expression可以直接配置bean名称就可以,Camunda会自动调用其方法。

          • 还是需要注入容器才行。
          import org.camunda.bpm.engine.delegate.DelegateExecution;
          import org.camunda.bpm.engine.delegate.JavaDelegate;
          import org.springframework.stereotype.Component;
          
          /**
           * #{delegateExpressionComponent}
           */
          @Component("delegateExpressionComponent")
          public class DelegateExpressionpythonComponent implements JavaDelegate {
          
              @Override
              public void execute(DelegateExecution execution) throws Exception {
                  System.out.println("DelegateExpressionComponent:" + execution.getProcessInstanceId());
              }
          }
          

          解读Camunda中强大的监听服务

          流程图

          <?xml version="1.0" encoding="UTF-8"?>
          <bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:camunda="http://camunda.org/schema/1.0/bpmn" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:modeler="http://camunda.org/schema/modeler/1.0" id="Definitions_13pugtj" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="5.19.0" modeler:executionPlatform="Camunda Platform" modeler:executionPlatformVersion="7.20.0">
            <bpmn:process id="Process_1dnzxeh" name="service" isExecutable="true" camunda:historyTimeToLive="180">
              <bpmn:extensionElements>
                <camunda:executionListener class="com.example.workflow.delegate.CustomExecutionListener" event="end" />
                <camunda:executionListener class="com.example.workflow.delegate.CustomExecutionListener" event="start" />
              </bpmn:extensionElements>
              <bpmn:startEvent id="StartEvent_1">
                <bpmn:extensionElements>
                  <camunda:executionListener class="com.example.workflow.delegate.CustomExecutionListener" event="start" />
                </bpmn:extensionElements>
                <bpmn:outgoing>Flow_0eji7wy</bpmn:outgoing>
              </bpmn:startEvent>
              <bpmn:serviceTask id="Activity_1claer7" name="bzService" camunda:class="com.example.workflow.delegate.CustomJavaDelegate">
                <bpmn:incoming>Flow_0eji7wy</bpmn:incoming>
                <bpmn:outgoing>Flow_0c190eu</bpmn:outgoing>
              </bpmn:serviceTask>
              <bpmn:sequenceFlow id="Flow_0eji7wy" sourceRef="StartEvent_1" targetRef="Activity_1claer7" />
              <bpmn:sequenceFlow id="Flow_0c190eu" sourceRef="Activity_1claer7" targetRef="Activity_1xjraoy" />
              <bpmn:userTask id="Activity_1xjraoy" name="userTask">
                <bpmn:extensionElements>
                  <camunda:taskListener class="com.example.workflow.delegate.CustomTaskListener" event="create" id="Lid255" />
                  <camunda:executionListener class="com.example.workflow.delegate.CustomExecutionListener" event="start" />
                </bpmn:extensionElements>
                <bpmn:incoming>Flow_0c190eu</bpmn:incoming>
                <bpmn:outgoing>Flow_0383lfn</bpmn:outgoing>
              </bpmn:userTask>
              <bpmn:endEvent id="Event_0aws3kb">
                <bpmn:extensionElements>
                  <camunda:executionListener class="com.example.workflow.delegate.CustomExecutionListener" event="start" />
                </bpmn:extensionElements>
                <bpmn:incoming>Flow_0383lfn</bpmn:incoming>
              </bpmn:endEvent>
              <bpmn:sequenceFlow id="Flow_0383lfn" sourceRef="Activity_1xjraoy" targetRef="Event_0aws3kb" />
            </bpmn:process>
            <bpmndi:BPMNDiagram id="BPMNDiagram_1">
              <bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Process_1dnzxeh">
                <bpmndi:BPMNShape id="_BPMNShape_StartEvent_2" bpmnElement="StartEvent_1">
                  <dc:Bounds x="179" y="99" width="36" height="36" />
                </bpmndi:BPMNShape>
                <bpmndi:BPMNShape id="Activity_04xt5m2_di" bpmnElement="Activity_1claer7">
                  <dc:Bounds x="280" y="77" width="100" height="80" />
                  <bpmndi:BPMNLabel />
                </bpmndi:BPMNShape>
                <bpmndi:BPMNShape id="Activity_1frv2ve_di" bpmnElement="Activity_1xjraoy">
                  <dc:Bounds x="450" y="77" width="100" height="80" />
                  <bpmndi:BPMNLabel />
                </bpmndi:BPMNShape>
                <bpmndi:BPMNShape id="Event_0aws3kb_di" bpmnElement="Event_0aws3kb">
                  <dc:Bounds x="602" y="99" width="36" height="36" />
                </bpmndi:BPMNShape>
                <bpmndi:BPMNEdge id="Flow_0eji7wy_di" bpmnElement="Flow_0eji7wy">
                  <di:waypoint x="215" y="117" />
                  <di:waypoint x="280" y="117" />
                </bpmndi:BPMNEdge>
                <bpmndi:BPMNEdge id="Flow_0c190eu_di" bpmnElement="Flow_0c190eu">
                  <di:waypoint x="380" y="117" />
                  <di:waypoint x="450" y="117" />
                </bpmndi:BPMNEdge>
                <bpmndi:BPMNEdge id="Flow_0383lfn_di" bpmnElement="Flow_0383lfn">
                  <di:waypoint x="550" y="117" />
                  <di:waypoint x="602" y="117" />
                </bpmndi:BPMNEdge>
              </bpmndi:BPMNPlane>
            </bpmndi:BPMNDiagram>
          </bpmn:definitions>
          

          总结

          以上为个人经验,希望能给大家一个参考,也希望大家多多支持编程客栈(www.devze.com)。

          0

          上一篇:

          下一篇:

          精彩评论

          暂无评论...
          验证码 换一张
          取 消

          最新开发

          开发排行榜