当前位置: 首页 > news >正文

java每日精进 7.25【流程设计3.0(网关+边界事件)】

1.网关

在BPMN 2.0(业务流程建模与标记法)中,网关是用来控制流程走向的元素,就像路口的红绿灯或岔路口,用来决定流程接下来该走哪条路。它的图形是一个菱形,内部有不同的小图标,表示不同类型的网关。网关可以用来拆分流程(一条路分成多条)或合并流程(多条路汇成一条),主要用于处理复杂的流程逻辑。

Flowable(一个基于BPMN 2.0的流程引擎)中常用的网关有四种:

  1. 排他网关(Exclusive Gateway):只能选一条路走。
  2. 并行网关(Parallel Gateway):可以同时走多条路或等待多条路汇合。
  3. 包容网关(Inclusive Gateway):可以根据条件走多条路或等待部分路汇合。
  4. 事件网关(Event Gateway):根据事件触发来选择走哪条路。

1.1 排他网关(Exclusive Gateway)

定义

排他网关(也叫XOR网关)是最常用的网关,作用是做选择题:从多条路中只能选一条走。它需要搭配条件来判断走哪条路,条件写在流出顺序流(sequenceFlow)上。

  • 工作原理
    • 流程到达排他网关时,会按顺序检查每条流出顺序流的条件。
    • 找到第一个条件为true的顺序流,就走这条路,其他路被忽略。
    • 如果所有条件都为false,但定义了默认顺序流,就走默认路。
    • 如果没有默认路且所有条件都为false,流程会抛出异常(流程中断)。
    • 建议每条顺序流都设置条件,没条件的顺序流默认算true。
    • 排他网关不负责合并,只要有一个流入的顺序流到达,它就开始判断走哪条路。如果有多个分支到达,可能会重复执行后续路径(除非业务需要,否则要避免)。

图形标记

排他网关是一个菱形,里面有个**“X”**图标,表示“异或”(XOR,意思是“只能选一个”)。

XML代码

排他网关的XML定义很简单,只需要指定ID和默认顺序流(如果有):

<exclusiveGateway id="Gateway_1gse3sj" default="Flow_1gdshzv"/>

条件写在流出顺序流中,比如:

<sequenceFlow id="Flow_0mdfhgf" name="大于10000" sourceRef="Gateway_1gse3sj" targetRef="Activity_1gvbrzi">

<conditionExpression xsi:type="tFormalExpression">

${money>10000}

</conditionExpression>

</sequenceFlow>

代码示例解析

以下是文中给出的排他网关流程示例(简化后的流程:费用申请审批):

<process id="ServiceSpringCloudBackServiceProcess" name="服务-Springcloud回调服务" isExecutable="true"><startEvent id="a39b8c7712bb742a7aa081cf731563c96" /><userTask id="ad7ca5657f18f4e64aa6e309db12fc47b" name="费用申请" /><sequenceFlow id="a653af6d1d2774d02afc0301d2f0121e2" sourceRef="a39b8c7712bb742a7aa081cf731563c96" targetRef="ad7ca5657f18f4e64aa6e309db12fc47b" /><exclusiveGateway id="Gateway_1gse3sj" default="Flow_1gdshzv"><incoming>Flow_0tmo406</incoming><outgoing>Flow_1gdshzv</outgoing><outgoing>Flow_0mdfhgf</outgoing></exclusiveGateway><userTask id="Activity_0b7092y" name="经理" /><userTask id="Activity_1gvbrzi" name="总监" /><userTask id="Activity_0ol5zjn" name="总经理" /><endEvent id="Event_1vogsar" /><sequenceFlow id="Flow_0tmo406" sourceRef="ad7ca5657f18f4e64aa6e309db12fc47b" targetRef="Gateway_1gse3sj" /><sequenceFlow id="Flow_1gdshzv" sourceRef="Gateway_1gse3sj" targetRef="Activity_0b7092y" /><sequenceFlow id="Flow_0mdfhgf" name="大于10000" sourceRef="Gateway_1gse3sj" targetRef="Activity_1gvbrzi"><conditionExpression xsi:type="tFormalExpression">${money>10000}</conditionExpression></sequenceFlow><sequenceFlow id="Flow_0c58ztv" sourceRef="Activity_0b7092y" targetRef="Activity_1gvbrzi" /><sequenceFlow id="Flow_0ovnf34" sourceRef="Activity_1gvbrzi" targetRef="Activity_0ol5zjn" /><sequenceFlow id="Flow_0odeyuq" sourceRef="Activity_0ol5zjn" targetRef="Event_1vogsar" /></process>
流程解释

这是一个费用申请审批流程

  1. 开始事件:流程从startEvent开始。
  2. 费用申请:员工提交费用申请(userTask: 费用申请)。
  3. 排他网关:流程到达exclusiveGateway: Gateway_1gse3sj,需要判断申请金额:
    • 如果金额大于10000(Flow_0mdfhgf条件:${money>10000}),走总监审批(userTask: 总监)。
    • 否则,走默认路径(Flow_1gdshzv),由经理审批(userTask: 经理)。
  4. 后续审批
    • 经理审批后,进入总监审批。
    • 总监审批后,进入总经理审批(userTask: 总经理)。
  5. 结束:总经理审批后,流程到达endEvent,结束。
现实场景

想象你在公司报销一笔费用:

  • 你提交报销申请(比如报销5000元或15000元)。
  • 系统检查金额:
    • 如果金额≤10000元,报销单给经理审批。
    • 如果金额>10000元,报销单直接给总监审批。
  • 经理审批后,报销单交给总监;总监审批后,交给总经理。
  • 最后由总经理决定是否通过。
关键点
  • 排他网关确保只有一条路被选中。
  • 条件${money>10000}是基于流程变量money判断的,变量值由用户或系统设置。
  • 默认路径(Flow_1gdshzv)保证即使条件不满足,流程也不会中断。

1.2 并行网关(Parallel Gateway)

定义

并行网关(也叫AND网关)用来处理并发,可以把流程拆成多条同时执行的路(分支,Fork),也可以把多条路汇合到一起(合并,Join)。它不看条件,所有流出的路都会走,所有流入的路都要到齐。

  • 分支(Fork):从并行网关流出后,每条顺序流都会生成一个并发分支,所有分支同时执行,忽略顺序流上的条件。
  • 合并(Join):所有流入并行网关的分支必须都到达,网关才会继续向下走。如果有分支没到,网关就一直等待。
  • 多进多出:一个并行网关可以同时分支和合并,先合并所有流入分支,再拆分成多个并发分支。

图形标记

并行网关是一个菱形,里面有个**“+”**图标,表示“与”(AND,意思是“所有都执行”)。

XML代码

<parallelGateway id="parallelGateway1" />

行为(分支或合并)由流入和流出顺序流决定。

现实场景

假设公司要开发一个产品:

  • 分支:产品开发需要同时进行“前端开发”和“后端开发”,并行网关将流程拆成两条路,两个团队同时开工。
  • 合并:只有当“前端开发”和“后端开发”都完成后,才能进入“测试”阶段。并行网关会等待两支团队都完成。

代码示例

<parallelGateway id="ForkGateway" /><sequenceFlow id="Flow1" sourceRef="ForkGateway" targetRef="Task_Frontend" /><sequenceFlow id="Flow2" sourceRef="ForkGateway" targetRef="Task_Backend" /><userTask id="Task_Frontend" name="前端开发" /><userTask id="Task_Backend" name="后端开发" /><sequenceFlow id="Flow3" sourceRef="Task_Frontend" targetRef="JoinGateway" /><sequenceFlow id="Flow4" sourceRef="Task_Backend" targetRef="JoinGateway" /><parallelGateway id="JoinGateway" />
  • ForkGateway:将流程拆分成“前端开发”和“后端开发”两条并发路径。
  • JoinGateway:等待两支团队完成任务后,流程继续。
关键点
  • 并行网关不检查条件,所有流出路径都会执行。
  • 合并时必须所有分支都到达,否则流程卡住。
  • 不要求分支和合并成对出现,一个分支网关可以对应多个合并网关,或无需合并。

1.3 包容网关(Inclusive Gateway)

定义

包容网关是排他网关和并行网关的结合体,可以根据条件选择多条路同时走(分支),也可以等待部分分支汇合(合并)。它比排他网关灵活,比并行网关有条件控制。

  • 分支(Fork)
    • 检查所有流出顺序流的条件,所有条件为true的路径都会并行执行。
    • 如果所有条件都为false,但有默认路径,就走默认路径。
    • 如果没有默认路径且所有条件为false,抛出异常。
  • 合并(Join)
    • 等待所有“可以到达”网关的分支都到达,才继续向下走。
    • “可以到达”是指:流程实例中存在一条路径能到达网关(忽略条件)。
    • 比如,如果某个分支压根没被触发,网关不会等它。
  • 多进多出:可以同时合并和分支,先合并所有可到达的流入分支,再根据条件拆分成多个并行分支。

图形标记

包容网关是一个菱形,里面有个圆圈图标。

XML代码

<inclusiveGateway id="inclusiveGateway1" />

代码示例解析

以下是文中给出的包容网关流程示例(请假审批流程):

<process id="InclusiveGatewayTest" name="网关-包容网关" isExecutable="true"><startEvent id="a63caeb191435462eb8fc789b998b0b02" /><userTask id="a2a3d2965e93841769298862145315216" name="请假申请" /><sequenceFlow id="a10afa5b876a14ef1927568c25d82532d" sourceRef="a63caeb191435462eb8fc789b998b0b02" targetRef="a2a3d2965e93841769298862145315216" /><inclusiveGateway id="Gateway_0wdovry" /><sequenceFlow id="Flow_01gl4se" sourceRef="a2a3d2965e93841769298862145315216" targetRef="Gateway_0wdovry" /><userTask id="Activity_0n2utd2" name="HR实习生审批" /><sequenceFlow id="Flow_0poec43" name="天数<3" sourceRef="Gateway_0wdovry" targetRef="Activity_0n2utd2"><conditionExpression xsi:type="tFormalExpression">${leaveDays<3}</conditionExpression></sequenceFlow><userTask id="Activity_1jqu87g" name="HR助理审批" /><sequenceFlow id="Flow_048awuq" name="天数>=3" sourceRef="Gateway_0wdovry" targetRef="Activity_1jqu87g"><conditionExpression xsi:type="tFormalExpression">${leaveDays>=3}</conditionExpression></sequenceFlow><userTask id="Activity_0i4f84q" name="直属领导审批" /><sequenceFlow id="Flow_1ifcgzs" name="天数>=1" sourceRef="Gateway_0wdovry" targetRef="Activity_0i4f84q"><conditionExpression xsi:type="tFormalExpression">${leaveDays>=1}</conditionExpression></sequenceFlow><inclusiveGateway id="Gateway_1byuti3" /><sequenceFlow id="Flow_0evatt3" sourceRef="Activity_0n2utd2" targetRef="Gateway_1byuti3" /><sequenceFlow id="Flow_1t3shqg" sourceRef="Activity_1jqu87g" targetRef="Gateway_1byuti3" /><userTask id="Activity_1ox2rws" name="HR经理审批" /><sequenceFlow id="Flow_0tc6xkx" sourceRef="Gateway_1byuti3" targetRef="Activity_1ox2rws" /><inclusiveGateway id="Gateway_02v0l7w" /><sequenceFlow id="Flow_0o8l6c2" sourceRef="Activity_1ox2rws" targetRef="Gateway_02v0l7w" /><sequenceFlow id="Flow_0s50mvn" sourceRef="Activity_0i4f84q" targetRef="Gateway_02v0l7w" /><endEvent id="Event_0cvo3tf" /><sequenceFlow id="Flow_120xxfs" sourceRef="Gateway_02v0l7w" targetRef="Event_0cvo3tf" /></process>
流程解释

这是一个请假审批流程

  1. 开始事件:员工提交请假申请(userTask: 请假申请)。
  2. 第一个包容网关(Gateway_0wdovry):根据请假天数(leaveDays)决定走哪些审批路径:
    • 如果leaveDays < 3,需要HR实习生审批(userTask: HR实习生审批)。
    • 如果leaveDays >= 3,需要HR助理审批(userTask: HR助理审批)。
    • 如果leaveDays >= 1,需要直属领导审批(userTask: 直属领导审批)。
    • 比如,员工请5天假,条件leaveDays>=3和leaveDays>=1都满足,流程会同时走HR助理审批和直属领导审批两条路。
  3. 第二个包容网关(Gateway_1byuti3):等待HR实习生审批和HR助理审批(如果触发了)完成,合并后进入HR经理审批(userTask: HR经理审批)。
  4. 第三个包容网关(Gateway_02v0l7w):等待HR经理审批和直属领导审批(如果触发了)完成,流程结束。
现实场景

假设你请假:

  • 请2天假:触发HR实习生审批(leaveDays<3)和直属领导审批(leaveDays>=1)。
  • 请5天假:触发HR助理审批(leaveDays>=3)和直属领导审批(leaveDays>=1)。
  • 流程会等待触发了的审批都完成,再交给HR经理审批,最后由HR经理和直属领导的审批结果决定是否通过。
关键点
  • 包容网关允许多条路径并行,根据条件决定走哪些路。
  • 合并时只等“可以到达”的分支,比如请2天假时,HR助理审批没触发,网关不会等它。
  • 建议设置默认路径,避免所有条件为false导致流程中断。

1.4 事件网关(Event Gateway)

定义

事件网关根据事件来决定走哪条路,而不是条件。它会暂停流程,等待某个事件(如定时器、消息)触发,然后走触发事件的路径,其他路径被取消。

  • 工作原理
    • 事件网关的每个流出顺序流必须连接到一个中间捕获事件(如定时器事件、信号事件)。
    • 到达网关时,流程暂停,为每个流出顺序流订阅事件。
    • 哪个事件先触发,流程就走那条路,其他订阅被取消。
  • 约束
    • 必须有两条或以上流出顺序流。
    • 流出顺序流只能连接中间捕获事件,不支持接收任务(Receive Task)。
    • 每个中间捕获事件只能有一个入口顺序流。

图形标记

事件网关是一个菱形,里面有个五边形图标。

XML代码

<eventBasedGateway id="exclusiveGateway1" />

代码示例解析

以下是文中给出的事件网关流程示例(客户投诉处理流程):

<signal id="alertSignal" name="alert" flowable:scope="global" /><process id="EventBasedGatwayTest" name="网关-事件网关" isExecutable="true"><startEvent id="ab90dd1d6552e49c09dec232671467890" /><userTask id="a53b48e07e88d4adb8b65bf3ab3460e0a" name="客户投诉" /><sequenceFlow id="a6171b16076dd41b6a67d25fd838218c4" sourceRef="ab90dd1d6552e49c09dec232671467890" targetRef="a53b48e07e88d4adb8b65bf3ab3460e0a" /><eventBasedGateway id="Gateway_0pspvvy" /><sequenceFlow id="Flow_0h5e59j" sourceRef="a53b48e07e88d4adb8b65bf3ab3460e0a" targetRef="Gateway_0pspvvy" /><intermediateCatchEvent id="Event_0f966w5" name="3分钟"><timerEventDefinition><timeDuration>PT2M</timeDuration></timerEventDefinition></intermediateCatchEvent><sequenceFlow id="Flow_0ajw2tf" sourceRef="Gateway_0pspvvy" targetRef="Event_0f966w5" /><intermediateCatchEvent id="Event_0g20b6y" name="信号"><signalEventDefinition signalRef="alertSignal" /></intermediateCatchEvent><sequenceFlow id="Flow_1w1y6zy" sourceRef="Gateway_0pspvvy" targetRef="Event_0g20b6y" /><userTask id="Activity_0aug760" name="二级客服处理" /><sequenceFlow id="Flow_0sqnwot" sourceRef="Event_0f966w5" targetRef="Activity_0aug760" /><userTask id="Activity_1wlis7z" name="一级客户处理" /><sequenceFlow id="Flow_1x3g9hf" sourceRef="Event_0g20b6y" targetRef="Activity_1wlis7z" /><endEvent id="Event_139njtd" /><sequenceFlow id="Flow_143bcf9" sourceRef="Activity_0aug760" targetRef="Event_139njtd" /><sequenceFlow id="Flow_1i2cmpp" sourceRef="Activity_1wlis7z" targetRef="Event_139njtd" /></process>
流程解释

这是一个客户投诉处理流程

  1. 开始事件:客户提交投诉(userTask: 客户投诉)。
  2. 事件网关(Gateway_0pspvvy):流程暂停,订阅两个事件:
    • 定时器事件(Event_0f966w5):等待3分钟(PT2M表示2分钟,可能是笔误)。
    • 信号事件(Event_0g20b6y):等待“alert”信号。
  3. 事件触发
    • 如果3分钟内没收到信号,定时器触发,流程走二级客服处理(userTask: 二级客服处理)。
    • 如果收到“alert”信号(比如客户再次投诉),信号事件触发,流程走一级客服处理(userTask: 一级客户处理)。
  4. 结束:处理完成后,流程到达endEvent。
现实场景

想象你在电商平台投诉订单问题:

  • 你提交投诉后,系统等待:
    • 如果3分钟内没进一步动作(比如你没再次联系客服),投诉交给二级客服处理。
    • 如果你很快再次发消息(触发“alert”信号),投诉升级到一级客服处理。
  • 哪个事件先发生,流程就走对应的路,其他路取消。
关键点
  • 事件网关是事件驱动,不看条件,只看哪个事件先触发。
  • 流出顺序流必须连接中间捕获事件,如定时器或信号。
  • 触发一个事件后,其他事件订阅取消,流程只走一条路。

总结与对比

网关类型图形标记行为特点使用场景
排他网关菱形+“X”只能走一条路,根据第一个true条件选择单选决策(如金额判断)
并行网关菱形+“+”所有路并行走,或等待所有路汇合并发任务(如多部门同时审批)
包容网关菱形+圆圈多条路并行走(条件为true),等待可到达路汇合灵活的多选(如请假天数审批)
事件网关菱形+五边形等待事件触发,走第一个触发事件的路事件驱动(如超时或信号处理)

具体实例总结

  1. 排他网关:费用报销时,金额>10000走总监审批,否则走经理审批。
  2. 并行网关:产品开发时,前端和后端同时开工,完成后一起进入测试。
  3. 包容网关:请假时,根据天数可能需要HR实习生、HR助理和直属领导并行审批。
  4. 事件网关:客户投诉后,等待3分钟或客户再次投诉,决定交给一级还是二级客服。

2.边界事件

在BPMN 2.0中,边界事件是一种特殊的中间事件,附着在某个流程活动(如用户任务、子流程等)的边界上,起到“监控”作用。当某个特定条件或事件发生时,边界事件会被触发,可能中断当前活动并改变流程走向。边界事件是**捕获型(Catching)**事件,等待外部触发(如消息、信号、错误等)。

边界事件分为:

  1. 中断型:触发后,当前活动被终止,流程走边界事件的后继路径。
  2. 非中断型:触发后,当前活动继续执行,同时流程走边界事件的后继路径。

Flowable支持的边界事件类型包括:

  • 消息边界事件
  • 信号边界事件
  • 错误边界事件
  • 定时器边界事件
  • 取消边界事件
  • 补偿边界事件

下面逐一解释每种边界事件的定义、用途、代码和示例。


2.1 消息边界事件(Message Boundary Interrupting Event)

定义

消息边界事件附着在某个活动(如用户任务或子流程)上,监听特定消息的到来。当消息到达时,事件触发,流程可能中断当前活动,沿着边界事件的后继路径继续。

  • 中断型(cancelActivity="true"):触发后,当前活动被终止。
  • 非中断型(cancelActivity="false"):触发后,当前活动继续,同时走边界事件路径。
  • 消息可以来自流程中的消息抛出事件(如中间抛出事件或结束事件)或通过API触发。

图形标记

消息边界事件是一个圆圈(中间事件标志),附着在活动边界上,内部有一个信封图标(白色,表示捕获)。中断型用实线,非中断型用虚线。

XML代码

xml

收起自动换行

复制

<message id="theMessage" name="newInvoiceMessage" />

<process id="messageBoundaryInterrputingEventProcess">

<userTask id="usertask1" name="审批任务" />

<boundaryEvent id="messageBoundaryInterrputingEvent" name="Timer" attachedToRef="usertask1" cancelActivity="false">

<messageEventDefinition messageRef="theMessage" />

</boundaryEvent>

</process>

  • message:定义消息,id="theMessage",name="newInvoiceMessage"。
  • userTask:被监控的活动(usertask1)。
  • boundaryEvent:消息边界事件,attachedToRef="usertask1"表示附着在usertask1上,messageRef="theMessage"引用消息,cancelActivity="false"表示非中断型。

触发方式

  1. 流程内部:通过流程中的消息抛出事件(如messageIntermediateThrowingEvent)或消息结束事件触发。
  2. API触发:使用Flowable的runtimeService.messageEventReceived方法:
    • runtimeService.messageEventReceived("newInvoiceMessage", executionId):发送消息到指定执行流。
    • runtimeService.messageEventReceived("newInvoiceMessage", executionId, processVariables):发送消息并更新流程变量。
现实场景

假设你在一个审批流程中:

  • 你提交了一个采购申请(userTask: 审批任务),等待经理审批。
  • 流程设计了一个消息边界事件,监听“紧急通知”消息。
  • 如果审批过程中收到“紧急通知”(比如通过API发送),边界事件触发:
    • 如果是中断型,审批任务被取消,流程可能跳转到“紧急处理”任务。
    • 如果是非中断型,审批任务继续,同时启动“紧急处理”任务。

代码示例解析

在上述XML中:

  • 流程有一个用户任务usertask1(审批任务)。
  • 消息边界事件messageBoundaryInterrputingEvent监听newInvoiceMessage消息,附着在usertask1上,非中断型。
  • 当收到newInvoiceMessage消息时,流程会沿边界事件的后继顺序流执行,同时usertask1继续运行。

2.2 信号边界事件(Signal Boundary Interrupting Event)

定义

信号边界事件类似于消息边界事件,但监听的是信号,信号是全局性的,可以被流程引擎内多个流程实例捕获。信号可以来自流程中的信号抛出事件或API触发。

  • 中断型(cancelActivity="true"):触发后终止当前活动。
  • 非中断型(cancelActivity="false"):触发后当前活动继续。
  • 信号默认是全局作用域,但可以通过flowable:scope="processInstance"限制为当前流程实例。

图形标记

信号边界事件是一个圆圈,附着在活动边界,内部有三角形信号图标(白色,表示捕获)。中断型用实线,非中断型用虚线。

XML代码

xml

收起自动换行

复制

<signal id="theSignal" name="The Signal" />

<process id="signalBoundaryInterrputingEventProcess">

<userTask id="usertask1" name="测试信号任务" />

<boundaryEvent id="signalBoundaryInterrputingEvent" name="Timer" attachedToRef="usertask1" cancelActivity="false">

<signalEventDefinition signalRef="theSignal" />

</boundaryEvent>

</process>

  • signal:定义信号,id="theSignal",name="The Signal"。
  • userTask:被监控的任务(usertask1)。
  • boundaryEvent:信号边界事件,attachedToRef="usertask1",signalRef="theSignal"引用信号,cancelActivity="false"表示非中断型。
  • 限制作用域:可添加flowable:scope="processInstance",如:

    xml

    收起自动换行

    复制

    <signal id="alertSignal" name="alert" flowable:scope="processInstance" />

触发方式

  1. 流程内部:通过信号抛出事件(如signalIntermediateThrowingEvent)或信号结束事件触发。
  2. API触发
    • runtimeService.signalEventReceived("The Signal"):发送信号给所有订阅的处理器。
    • runtimeService.signalEventReceived("The Signal", executionId):发送信号给指定执行流。
现实场景

假设你在处理订单:

  • 订单处理任务(userTask: 测试信号任务)正在进行。
  • 信号边界事件监听“库存不足”信号(The Signal)。
  • 如果系统中某处触发了“库存不足”信号(比如仓库系统抛出信号):
    • 中断型:订单处理任务被取消,流程跳转到“通知客户”任务。
    • 非中断型:订单处理继续,同时启动“通知客户”任务。
  • 如果设置了flowable:scope="processInstance",只有当前订单流程会响应信号。

代码示例解析

在上述XML中:

  • 信号theSignal定义为全局信号。
  • 信号边界事件附着在usertask1上,非中断型。
  • 当收到The Signal信号时,流程沿边界事件的后继路径执行,同时usertask1继续运行。

2.3 错误边界事件(Error Boundary Interrupting Event)

定义

错误边界事件用于捕获附着活动抛出的BPMNError异常,通常用于子流程或调用活动。当错误发生时,当前活动被销毁,流程沿错误边界事件的后继路径继续。

  • 总是中断型:触发后,当前活动被终止。
  • 错误通过errorCode匹配,捕获特定错误或任何错误。

图形标记

错误边界事件是一个圆圈,附着在活动边界,内部有闪电图标(白色,表示捕获),用实线表示。

XML代码

xml

收起自动换行

复制

<error id="theError" errorCode="410" />

<process id="messageBoundaryInterrputingEventProcess">

<userTask id="usertask1" name="处理任务" />

<boundaryEvent id="errorBoundaryInterrputingEvent" name="Timer" attachedToRef="usertask1" cancelActivity="true">

<errorEventDefinition errorRef="theError" />

</boundaryEvent>

</process>

  • error:定义错误,id="theError",errorCode="410"。
  • userTask:被监控的任务(usertask1)。
  • boundaryEvent:错误边界事件,attachedToRef="usertask1",errorRef="theError"引用错误,cancelActivity="true"表示中断型。

触发规则

  • 如果errorRef引用了定义的错误(如theError),只捕获匹配errorCode的错误(410)。
  • 如果errorRef不匹配任何错误,errorRef被当作errorCode使用。
  • 如果未设置errorRef,捕获所有错误。
  • 子流程中,错误会向上冒泡,直到找到匹配的错误边界事件。
现实场景

假设你在一个支付流程中:

  • 支付任务(userTask: 处理任务)尝试扣款。
  • 如果扣款失败,抛出错误(BPMNError with errorCode="410",表示“余额不足”)。
  • 错误边界事件捕获错误,终止支付任务,流程跳转到“通知用户余额不足”任务。

代码示例解析

在上述XML中:

  • 错误theError定义为errorCode="410"。
  • 错误边界事件附着在usertask1上,捕获410错误。
  • 当usertask1抛出410错误时,任务被终止,流程沿边界事件路径继续。

2.4 定时器边界事件(Timer Boundary Interrupting Event)

定义

定时器边界事件附着在活动上,设置一个定时器,当定时器触发时,流程沿边界事件的后继路径继续。

  • 中断型(cancelActivity="true"):触发后终止当前活动。
  • 非中断型(cancelActivity="false"):触发后当前活动继续。
  • 定时器需要开启Flowable的作业执行器(configuration.setAsyncExecutorActivate(true))。

图形标记

定时器边界事件是一个圆圈,附着在活动边界,内部有时钟图标(白色,表示捕获)。中断型用实线,非中断型用虚线。

XML代码

xml

收起自动换行

复制

<process id="timerBoundaryEventProcess">

<userTask id="usertask1" name="审批" />

<boundaryEvent id="timerBoundaryEvent" name="Timer" attachedToRef="usertask1" cancelActivity="false">

<timerEventDefinition>

<timeDuration>PT1M</timeDuration>

</timerEventDefinition>

</boundaryEvent>

</process>

  • userTask:被监控的任务(usertask1)。
  • boundaryEvent:定时器边界事件,attachedToRef="usertask1",timeDuration="PT1M"表示1分钟后触发,cancelActivity="false"表示非中断型。
  • 定时器类型
    • timeDate:指定时间触发(如2023-07-14T12:12:14)。
    • timeDuration:指定时间段后触发(如PT1M表示1分钟)。
    • timeCycle:定期触发(如R2/PT1M表示每1分钟触发2次)。
现实场景

设计一个客户投诉流程:

  • 一线客服处理投诉(userTask: 审批),附着一个2小时的定时器边界事件。
  • 如果2小时内未完成:
    • 中断型:一线客服任务终止,投诉转给二线客服。
    • 非中断型:一线客服继续处理,同时通知二线客服介入。

代码示例解析

在上述XML中:

  • 定时器边界事件附着在usertask1(审批任务)上,1分钟后触发,非中断型。
  • 触发后,流程沿边界事件路径执行,usertask1继续运行。

2.5 取消边界事件(Cancel Boundary Interrupting Event)

定义

取消边界事件只用于事务性子流程,在事务取消时触发。触发后:

  1. 中断事务子流程内所有活动。
  2. 执行子流程内已完成活动的补偿边界事件(同步执行)。
  3. 沿取消边界事件的后继路径继续。
  • 总是中断型:触发后事务子流程被终止。
  • 每个事务子流程只能有一个取消边界事件。

图形标记

取消边界事件是一个圆圈,附着在事务子流程边界,内部有取消图标(白色,表示捕获),用实线表示。

XML代码

xml

收起自动换行

复制

<process id="cancelBoundaryEventProcess">

<transaction id="transactionSubProcess" name="事务子流程" />

<boundaryEvent id="cancelBoundaryEvent" name="Cancel" attachedToRef="transactionSubProcess">

<cancelEventDefinition />

</boundaryEvent>

</process>

  • transaction:事务子流程(transactionSubProcess)。
  • boundaryEvent:取消边界事件,attachedToRef="transactionSubProcess",使用cancelEventDefinition。
现实场景

假设你预订酒店(事务子流程):

  • 事务子流程包括“扣款”和“预订房间”。
  • 如果扣款失败,触发取消边界事件:
    • 事务子流程终止。
    • 执行补偿(如退款)。
    • 流程跳转到“通知用户预订失败”。

代码示例解析

在上述XML中:

  • 取消边界事件附着在transactionSubProcess上。
  • 当事务取消时,触发事件,终止子流程,执行补偿,沿后继路径继续。

2.6 补偿边界事件(Compensate Boundary Interrupting Event)

定义

补偿边界事件用于处理已完成活动的补偿逻辑,在事务取消或补偿中间事件触发时执行。补偿通过关联的补偿处理器(isForCompensation="true")完成。

  • 触发时机:活动完成后,订阅保留,直到流程实例结束或补偿触发。
  • 特点
    • 补偿处理器通过关联(association)连接,不是顺序流。
    • 补偿处理器没有入口/出口顺序流,仅在补偿时执行。
    • 不支持附着在子流程上。

图形标记

补偿边界事件是一个圆圈,附着在活动边界,内部有回退箭头图标(白色,表示捕获),用实线表示。

XML代码

xml

收起自动换行

复制

<process id="compensateBoundaryEventProcess">

<userTask id="usertask1" name="审批" />

<boundaryEvent id="compensateBoundaryEvent1" name="Compensate" attachedToRef="usertask1">

<compensateEventDefinition />

</boundaryEvent>

<serviceTask id="serviceTask1" name="CompensationHandler" isForCompensation="true" flowable:class="**.**.**.****" />

<association id="association1" sourceRef="compensateBoundaryEvent1" targetRef="serviceTask1" associationDirection="None" />

</process>

  • userTask:被监控的任务(usertask1)。
  • boundaryEvent:补偿边界事件,attachedToRef="usertask1"。
  • serviceTask:补偿处理器,isForCompensation="true",通过association连接。

触发方式

  1. 事务子流程取消,触发补偿。
  2. 流程中的补偿中间事件触发。
现实场景

假设你预订机票:

  • 审批任务(userTask: 审批)完成,记录了预订。
  • 如果事务取消(如支付失败),补偿边界事件触发,执行补偿处理器(serviceTask1),取消预订并退款。

代码示例解析

在上述XML中:

  • 补偿边界事件附着在usertask1上,连接到补偿处理器serviceTask1。
  • 当补偿触发时,执行serviceTask1(如退款逻辑),usertask1已完成,不会被中断。

总结与对比

边界事件类型图形标记触发条件行为使用场景
消息信封图标消息到达中断/非中断外部消息通知(如紧急处理)
信号三角形图标信号触发中断/非中断全局事件(如库存不足)
错误闪电图标BPMNError中断异常处理(如支付失败)
定时器时钟图标时间到达中断/非中断超时处理(如投诉超2小时)
取消取消图标事务取消中断事务子流程取消(如预订失败)
补偿回退箭头补偿触发非中断补偿逻辑(如退款)

具体实例总结

  1. 消息边界事件:采购审批中,收到“紧急通知”消息,跳转到紧急处理(非中断型允许审批继续)。
  2. 信号边界事件:订单处理中,收到“库存不足”信号,通知客户(全局信号可跨流程)。
  3. 错误边界事件:支付任务失败,抛出“余额不足”错误,跳转到通知用户。
  4. 定时器边界事件:投诉处理超2小时,自动转给二线客服。
  5. 取消边界事件:酒店预订事务取消,触发退款并通知用户。
  6. 补偿边界事件:机票预订后取消,执行退款逻辑。
http://www.lryc.cn/news/599968.html

相关文章:

  • 【Linux系统】基础IO(下)
  • 解决笔记本合盖开盖DPI缩放大小变 (异于网传方法,Win11 24H2)
  • STM32的WI-FI通讯(HAL库)
  • 【电赛学习笔记】MaxiCAM 项目实践——二维云台追踪指定目标
  • 嵌入式Linux裸机开发笔记8(IMX6ULL)主频和时钟配置实验(3)
  • vue 渲染 | 不同类型的元素渲染的方式(vue组件/htmlelement/纯 html)
  • linux配置ntp时间同步
  • 前端核心进阶:从原理到手写Promise、防抖节流与深拷贝
  • ERNIE-4.5-0.3B 实战指南:文心一言 4.5 开源模型的轻量化部署与效能跃升
  • Agentic RAG理解和简易实现
  • 计算机体系结构中的中断服务程序ISR是什么?
  • haproxy集群
  • Java测试题(上)
  • Spring之【Bean后置处理器】
  • sam2环境安装
  • JAVA语法糖
  • JAVA同城服务家政服务家政派单系统源码微信小程序+微信公众号+APP+H5
  • 探索 Sui 上 BTCfi 的各类资产
  • 在DolphinScheduler执行Python问题小记
  • DP4871音频放大芯片3W功率单通道AB类立体声/音频放大器
  • 3N90-ASEMI电源管理领域专用3N90
  • 【前端】JavaScript文件压缩指南
  • 文件包含学习总结
  • reflections:Java非常好用的反射工具包
  • 【linux】Haproxy七层代理
  • 如何理解泊松分布
  • 在 IntelliJ IDEA 中打开这个用于设置 Git 用户名(Name)和邮箱(Email)的特定弹窗
  • JAVA知识点(三):Spring与ORM框架
  • 【RDMA】Adapters PRM Mellanox Adapters Programmer’s Reference mellanox网卡编程手册0.52
  • Linux库——库的制作和原理(1)_回顾动静态库、制作使用库