Camunda入门(三) - BPMN、DMN、Form相关模型介绍(持续补充...)

1. BPMN介绍

BPMN - Business Process Model and Notation

可以类比上小学时学的流程图😂,
在这里插入图片描述

将流程图和BPMN做个最简单的类比如下表:

流程图元素流程图示例BPMN对应元素BPMN示例
开始在这里插入图片描述开始事件Start Event在这里插入图片描述
活动在这里插入图片描述任务Task在这里插入图片描述
判断在这里插入图片描述网关Gateway在这里插入图片描述
结束在这里插入图片描述结束事件End Event在这里插入图片描述
连接线在这里插入图片描述顺序流Sequence flow在这里插入图片描述

可以发现从流程图可以很平滑的过渡到BPMN模型,
简单理解:BPMN就是流程图的升级版,
当然BPMN的功能远不止表格中列出的这些,
接下来的会逐步探索BPMN的相关功能。

1.1 Event - 事件

接收事件(等待事件发生),触发事件(发送事件),
进而触发流程执行、改变流程走向、结束流程等。
在这里插入图片描述

关于事件的分类详见下表(其中橘色的事件为Camunda支持的)
在这里插入图片描述

捕获事件阻塞等待事件通知) 都是空心图标
抛出事件 (抛出结束事件 或者 抛出事件通知后继续执行) 都是实心图标
中断事件 (中断原流程 且 开启新流程) 都是实线圆(子流程中断开始事件、边界型中断中间事件)
非中断事件 (不中断原流程 且 开启新流程) 都是虚线圆(子例程非中断开始事件、边界型非中断中间事件)
开始事件(单实线圆,空心图标,子流程虚线中断)都是捕获事件
结束事件(加粗单实线圆,实心图标)都是抛出事件
中间事件(双实线圆)包括捕捉事件(空心图标)、抛出事件(实心图标)
边界型中间事件(双实线圆,附加在活动、子流程边界,虚线中断)都是捕获事件

1.1.1 开始事件

  • 空白开始事件Blank
  • 定时器开始事件Timer
  • *消息开始事件Message
  • *信号开始事件Signal
  • 条件开始事件Conditional
    在这里插入图片描述

1.1.2 中间事件

在这里插入图片描述

  • 捕获事件(Catch Event,空心图标)- 接收事件通知后,触发流程继续执行
    在这里插入图片描述

  • 抛出事件(Throw Event,实心图标)- 主动抛出事件通知,然后继续执行流程
    在这里插入图片描述

在这里插入图片描述

1.1.3 边界事件

在这里插入图片描述

  • 边界事件(Boundary Evant,亦成为附加中间事件,Attached Intermediate Events),附加到任务、子流程上的中间事件
    • 中断 - 边界事件
      若任务执行过程中发生附加事件,则取消当前任务,继续执行附加事件对应的流程,
      否则继续执行当前任务正常流程(非附件事件对应分支)
    • 非中断 - 边界事件
      若任务执行过程中发生附加事件,则继续执行当前任务(即后续流程),同时执行附加事件对应的流程,
      若当前任务执行过程中重复发生附加事件,则重复执行附加事件对应的流程,
      否则继续执行当前任务正常流程(非附件事件对应分支)
    • 补偿 - 边界事件
      仅在任务执行完成后,才会执行补偿边界事件连接的的补偿任务,
      补偿边界事件可由补偿结束事件补偿中间抛出事件触发,亦可由事务子流程取消结束事件触发。
      在这里插入图片描述

1.1.4 结束事件

在这里插入图片描述

1.2 Tasks - 任务

Task即为流程活动(对应单个执行步骤)的抽象。
在这里插入图片描述

1.2.1 Servcie Task - 调用外部服务

Service Task用于调用外部服务。

在这里插入图片描述

调用服务方式

调用服务的方式分为:

调用Java代码 - 实现JavaDelegate
  • Java Class - 指定代理类全路径(实现接口JavaDelegate、ActivityBehavior,抛异常则回滚到上一步),如:com.luo.demo.MyDelegate
  • Delegate Expression - 使用表达式来提取代理对象(实现接口JavaDelegate、ActivityBehavior),更适合SpringBoot环境,如:${myDelegateBean}
  • Expression - 调用方法表达式,如:${myBean.doWork()}
  • Expression - 解析值表达式(Evaluating a value expression)
External Task

在这里插入图片描述

  • External (External Task)
    • 指定task对应的topic
    • 由外部Worker通过REST API(Long Polling)主动获取并锁定(可指定超时时间)任务(亦支持Java API
    • 外部worker通知流程 完成Complete 或 失败Failure

Java API示例代码(需配合外层循环):

List<LockedExternalTask> tasks = processEngine.getExternalTaskService()
//最多一次拉取10条task,设置当前workerId为externalWorkerId(需唯一)
.fetchAndLock(10, "externalWorkerId")
  //指定查询的topic,及任务锁定超时时间(超时后可被其他worker获取到)
  .topic("AddressValidation", 60L * 1000L)
  .topic("ShipmentScheduling", 120L * 1000L)
  .execute();

for (LockedExternalTask task : tasks) {
  try {
    String topic = task.getTopicName();

    // work on task for that topic
    ...

    // if the work is successful, mark the task as completed
    if(success) {
      externalTaskService.complete(task.getId(), variables);
    }
    else {
      // if the work was not successful, mark it as failed
      externalTaskService.handleFailure(
        task.getId(),
        "externalWorkerId",
        "Address could not be validated: Address database not reachable",
        1, 10L * 60L * 1000L);
    }
  }
  catch(Exception e) {
    //... handle exception
  }
}

REST API代码示例:

 ExternalTaskClient client = ExternalTaskClient.create()
        .baseUrl("http://localhost:8080/engine-rest")
        .asyncResponseTimeout(10000) // long polling timeout
        .build();

    // subscribe to an external task topic as specified in the process
    client.subscribe("charge-card")
        .lockDuration(1000) // the default lock duration is 20 seconds, but you can override this
        .handler((externalTask, externalTaskService) -> {
          // Put your business logic here

          // Get a process variable
          String item = (String) externalTask.getVariable("item");
          Long amount = (Long) externalTask.getVariable("amount");

          LOGGER.info("Charging credit card with an amount of '" + amount + "'€ for the item '" + item + "'...");

          try {
              Desktop.getDesktop().browse(new URI("https://docs.camunda.org/get-started/quick-start/complete"));
          } catch (Exception e) {
              e.printStackTrace();
          }

          // Complete the task
          externalTaskService.complete(externalTask);
        })
        .open();
  }

SpringBoot ExternalTaskHandler示例代码:

@ExternalTaskSubscription(topicName = "payment-biz")
@Bean
public ExternalTaskHandler paymentBizHandler() {
    return (externalTask, externalTaskService) -> {
        //获取流程变量
        String productName = externalTask.getVariable(PRODUCT_NAME);
        Double productPrice = externalTask.getVariable(PRODUCT_PRICE);
        String paymentAssignee = externalTask.getVariable(PAYMENT_ASSIGNEE);
        Double productDiscountPrice = externalTask.getVariable(PRODUCT_DISCOUNT_PRICE);
        log.info("The External Task {} has been checked!", externalTask.getId());
        //完成任务
        externalTaskService.complete(externalTask);
        //完成任务且添加流程变量
        //externalTaskService.complete(externalTask, Variables.putValueTyped("creditScores", creditScoresObject));
        log.info("Payment SUCCESS - paymentAssignee={}, productName={}, productPrice={}, productDiscountPrice={}",
                paymentAssignee,
                productName,
                productPrice,
                productDiscountPrice);

        //任务失败
        //externalTaskService.handleFailure(
        //        externalTask,
        //        "errorMsg",
        //        "errorDetails",
        //        1,
        //        10L * 60L * 1000L);

    };
}
调用web服务(REST、SOAP)
外部任务优先级Priorities

External Task Priority,数字类型,值越大优先级越大,越先被外部worker查询到

List<LockedExternalTask> tasks =
  //第三个参数为true,则表示启用安装优先级查询external task
  externalTaskService.fetchAndLock(10, "externalWorkerId", true)
  .topic("AddressValidation", 60L * 1000L)
  .topic("ShipmentScheduling", 120L * 1000L)
  .execute();

for (LockedExternalTask task : tasks) {
  String topic = task.getTopicName();

  // work on task for that topic
  ...
}
Field注入

其中Java Class、Delegate Expression、External实现方式,支持Field注入
可通过Service Task对应的标签页Field Injections进行设置,
Camunda官方建议提供Setter方法支持Filed注入(兼容CDI)。

在这里插入图片描述

JavaDelegate示例代码:

//实现JavaDelegate(每次执行task都会新建对象实例)
public class ReverseStringsFieldInjected implements JavaDelegate {
	//定义待注入的Field(Camunda建议配置Setter方法进行注入)
    private Expression text1;
    private Expression text2;

    public void execute(DelegateExecution execution) {
      //获取流程变量
      String var = (String) execution.getVariable("input");
      //处理逻辑实现
      var = var.toUpperCase();
      //重写 或 设置新的流程变量
      execution.setVariable("input", var);
      
      //获取注入的Field
      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());
    }

	//Camunda官方建议提供Setter方法支持Filed注入(兼容CDI)
	public void setText1(Expression text1) {
		this.text1 = text1;
	}	
	public void setText2(Expression text2) {
		this.text2 = text2;
	}
  }

注:
在SpringBoot环境慎用Field注入,由于SpringBoot Bean默认Singleton(单例),
并发访问可能存在field覆盖冲突。

1.2.2 Business Rule Task - 业务规则任务(可绑定DMN)

如下图可通过Business Rule Task绑定单独的DMN文件中的Decision决策表格,
以此实现根据不同输入产生不同输出的效果,
DMN输出结果需通过Result Variable等设置进行映射,
映射之后才可供后续流程元素进行访问。
在这里插入图片描述

例如如上图中的Decision Ref中product-discount-rule即对应DMN模型中的Decision.id,
如下即为具体决策表格内容,关于DMN的介绍可参见本文第2章:2. DMN介绍
在这里插入图片描述

1.2.3 User Task - 委托给具体用户处理的任务,需要对应的用户进行处理

参考:https://docs.camunda.org/manual/latest/reference/bpmn20/tasks/user-task

  • assignee - 受托人(处理任务的人)
  • candidate users - 候选人(处理任务的多个人,由逗号分隔)
  • candidate groups - 候选组织(处理任务的多个组织,由逗号分隔)
  • 注: assignee、candidate users、candidate groups均支持表达式,例如:
    • ${bizUser} - 支持流程变量bizUser作为受托人
    • ${ldapService.findAllSales()} - 支持Spring/CDI bean的方法调用,返回结果为String或Collection<String>,下同
    • ${ldapService.findManagerForEmployee(emp)} - 支持Spring/CDI bean的方法调用,参数emp即对应流程变量emp
  • due to date - 到期时间
  • follow up date - 跟进时间

1.2.4 Input/Output Paramerters

参考:https://docs.camunda.org/manual/latest/user-guide/process-engine/variables/#input-output-variable-mapping
camunda提供输入、输出参数的转换映射,
即可通过表达式(解析之前已存在的流程变量并转换为新的变量)来提取变量,

  • Variable Assignment Type=String orExpression
  • Variable Assignment Value=具体的表达式

表达式示例如下:

  • ${myVar}
  • ${myResultMap.key1}

并将提取的值作为当前元素(如task)的:

  • 输入参数(Input Parameters) - 作为输入变量供当前活动使用
    • Local Variable Name - 输入变量名
  • 输出参数(Output Parameters) - 作为当前活动的输出变量
    • Process Variable Name - 输出变量名
      在这里插入图片描述
      在这里插入图片描述

1.3 Gateway - 网关

网关,即根据条件产生不同流程分支。
在这里插入图片描述

1.3.1 Exclusive Gateway - 排他网关(1入多出,仅1出执行,出带条件)

在这里插入图片描述

仅执行第一个条件为真的分支,
若均不为真,则报异常(可添加默认流)
在这里插入图片描述
顺序流分为条件流、默认流。
设置默认流参考:https://forum.camunda.org/t/gateway-default-flow/447/5
在这里插入图片描述

1.3.2 Parallel Gateway - 并行网关(多入多出,无条件)

在这里插入图片描述

并发执行(不评估条件)Fork或Join,

  • Fork - 分支
  • Join - 汇合(在其他分支都执行成功后统一汇合)
    在这里插入图片描述

1.3.3 Inclusive Gateway - 包含网关(多入多出,出带条件)

可看出Exclusive和Paralles网关的结合体,

  • Fork - 排他网关带条件多分支,并行执行
  • Join - 并行网关汇合
    在这里插入图片描述

1.3.4 Event Based Gateway - 基于事件的网关(1入多出,仅一出执行,出带事件)

在这里插入图片描述

通过捕获事件来决定执行分支(区别于排他网关根据条件),
仅执行第一个发生事件对应的分支,
且每个序列流分支均需连接到一个中间捕获事件。
在这里插入图片描述
在这里插入图片描述

1.4 Pool/Lane - 组织/角色

Pool - 池,表示组织、公司、系统
Lane - 泳道,表示参与者、角色
在这里插入图片描述
在这里插入图片描述

1.5 子流程

1.5.1 嵌入式子流程

  • 与主流程元素存在顺序流连接
  • 仅以唯一空白开始事件开始
  • 嵌入子流程为实线边框(区别于事件子流程为虚线)
    在这里插入图片描述

1.5.2 事件子流程

由事件触发的子流程

  • 与主流程元素不存在顺序流连接
  • 支持消息、定时器、信号、错误、补偿等开始事件(不支持空白开始事件)
  • 事件子流程为虚线边框(区别于嵌入事件子流程为实线)
  • 支持中断、非中断事件子流程
    • 中断(开始事件为实线边框) - 取消当前任务执行,转而执行事件子流程
    • 非中断(开始事件为虚线边框) - 继续执行当前任务,进而并发执行事件子流程
      在这里插入图片描述
      在这里插入图片描述
      在这里插入图片描述

1.5.3 事务子流程

嵌入式子流程,对一组活动进行分组,作为一个整体的所有活动同时成功或失败(终止和取消)。

  • 与主流程元素存在顺序流连接
  • 事务子流程为双实线边框
  • 可由事务子流程内的取消结束事件触发事务子流程回滚(触发子流程内的补偿边界事件的执行)
  • 亦可由事务子流程(成功执行)之后的中间抛出补偿事件触发事务子流程回滚(触发子流程内的补偿边界事件的执行)
  • 可在事务子流程上添加取消边界事件来接管取消后的事务子流程的流程走向
  • 事务子流程内的错误事件若未在事务子流程的作用域内被捕获,那么事务子流程被终止,且不会执行补偿。
    在这里插入图片描述
    在这里插入图片描述

1.5.4 调用活动

调用独立部署的流程(作为当前流程的子流程执行),
在调用活动执行完成后,再继续执行当前流程。
在这里插入图片描述

2. DMN介绍

DMN - Decision Model and Notation

定义规则模型,可与BPMN中Business Rule Task通过Decision.id进行绑定。
简单理解:类似可视化的Drools编辑器(规则引擎),
底层默认使用FEEL表达式。

2.1 Decision - 决策

2.1.1 Decision Table(id, name) - 决策表格

如下图新建Decision,默认类型即为Decision Table,可通过扳手图标🔧切换类型。
在这里插入图片描述
点击Decision左上角的蓝色图标,即可进入决策表编辑界面,决策表各组成部分如下图:
在这里插入图片描述

Input - 输入(1个或多个)
  • ID - 唯一ID
  • label - 显示标签
  • Expression - 提取输入值的表达式(根据Process Variables生成input值)
    • 变量名
    • 包含变量名的表达式
  • Expression Language - 表达式语言类型(默认FEEL
  • type - 提取出的输入值的类型(非必须,建议添加,可避免非法输入类型转换)
  • Input Variable - 提取出的输入值的存储变量名(默认cellInput),可用于后续规则中inputEntry表达式中 在这里插入图片描述
Output - 输出(1个或多个)
  • ID
  • Label - 显示标签
  • Ouput Name - 输出结果的存储变量名(后续流程中可通过变量名称引用此变量)
  • Type - 输出结果的类型(非必须,建议添加,可避免非法输出类型转换)
    在这里插入图片描述
Rule - 规则,一个决策表格由多行规则组成
  • Input Entry(Condition) - 规则的输入条件
  • 空的InputEntry表示永远为真(永远满足)
  • Output Entry(Conclusion) - 规则的输出结果
  • InputEntry和OutputEntry支持表达式
  • 当同一行的(多个)InputEntry都满足时则输出对应的(多个)OutputEntry
    在这里插入图片描述
Hit Policy - 规则匹配策略
Hit Policy说明示例
Unique仅有一条规则满足 或者 都不满足,若仅有一条满足则输出在这里插入图片描述
Any任何一条规则满足则输出(允许多条规则同时满足,但这些规则必须有相同的输出OutputEntry)在这里插入图片描述
First第一条满足则输出(允许多条规则同时满足,但仅第一条会被输出)在这里插入图片描述
Rule order允许多条规则满足,则按照规则顺序全部输出在这里插入图片描述
Collect允许多条规则满足,则按照任意(不确定)顺序全部输出
Collect策略允许指定聚合器Aggregators(仅输出一条)
  • Collect(Sum) - 求和输出
  • Collect(Min) - 最小值输出
  • Collect(Max) - 最大值输出
  • Collect(Count) - 结果数量输出
在这里插入图片描述

注:
DMN中表达式(默认使用FEEL)支持范围:

  • Input Expression: sets the input value for an input column of the decision table
  • Input Entry: used to determine if a rule of the decision table is applicable
  • Output Entry: returns a value which is added to the output of a matched rule of the decision table
  • Literal Expression: used to determine the value of a decision literal expression

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

2.1.2 Literal Expression - 字面量表达式

如下图新建Literal Expression,
即根据表达式提取决策结果,如调用bean方法获取结果。
在这里插入图片描述
在这里插入图片描述

3. Form介绍

即自定义表单,用于与BPMN Task进行绑定。
在这里插入图片描述

User Task Forms类型

参考:
https://docs.camunda.org/manual/latest/user-guide/task-forms

注: BPMN2.0中仅 StartEvent和UserTask支持链接form

FormType:

  • Embeeded Task Forms
    内嵌HTML或JS表单到TaskList中
  • Camunda Forms
    集成Camunda Modeler创建的Form,支持Form Key和Form Ref格式引用
  • External Task Forms
    链接自定义应用,Form不内嵌在TaskList中展示

Form Key

  • FORM-TYPE:LOCATION:FORM.NAME
    • FORM-TYPE
      • camunda-forms
      • embedded
    • LOCATION
      • demployment
        作为部署的一部分,在通过Modeler部署时需通过附件一起上传
        在这里插入图片描述

      • app
        form文件集成在war应用中,目录需放在 src/main/webapp/forms

    • FORM.NAME

例如

  • camunda-forms:deployment:payment.form
  • embedded:app:forms/FORM_NAME.html

Form Ref
仅支持绑定Camunda Form(Modeler创建)

  • camunda:formRef - key
  • camunda:formRefBinding
    • deployment - 位于同一deployment
    • latested - 最新版本
    • version - 指定版本,通过camunda:formRefVersion设置版本
  • camunda:formRefVersion

更多:

  • 23
    点赞
  • 78
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 16
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 16
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

罗小爬EX

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值