Skip to content

服务逻辑编排 ​

服务逻辑编排是一种基于流的编程,是一种数据流编程范式,也是一种基于组件的软件工程方式。 通过将程序分解为可重用的组件,定义其输入和输出端口;再把多个组件连接起来,形成一个数据流图,就是一个服务逻辑进程; 多个服务逻辑进程就可以实现一个业务应用的服务逻辑。

服务的常规需求 ​

一个服务接口,一般逻辑如下:

在这个过程中,复杂度主要集中在Service中,需要变量(定义、赋值)、判断、循环(跳出循环、进入下一个循环)、返回、异常(抛出和捕获)、事件(监听和触发)、定时执行、延时执行、调用(其他Service和其他接口)、事务和超时处理等。

变量 ​

给变量赋予常量、时间以及其他表达式,可以实现变量赋值或者计算,通过组件完成

类似Java代码:

java
String a = '123';
a = a + 1;

Date now = new Date();

判断 ​

可以提供跳过条件和排他网关、并行网关、包容网关,实现判断逻辑

跳过条件 ​

在组件上设置跳过条件,当表达式成立时,跳过执行组件逻辑,直接进入后续逻辑

类似Java逻辑如下:

java
if(!skipCondition) {
  // 执行业务逻辑
}

排他网关 ​

按顺序,执行第一个满足条件的分支

类似Java逻辑如下:

java
if (conditionA) {
  // 分支1
} else if (conditionB) {
  // 分支2
} else {
  // 默认分支
}

switch (key) {
case A:
  // 分支1
  break;
case B:
  // 分支2
  break;
default:
  // 默认分支
  break;
}

并行网关 ​

逻辑编排中并行网关作用不大,由于机制问题,并行和串行没有太大差别;

汇聚规则:当所有入口线都执行完成后,才能往后执行

包容网关 ​

执行满足条件的所有分支

类似Java逻辑如下:

java
if (conditionA || conditionB) {
  if (conditionA) {
    // 分支1
  }
  if (conditionB) {
    // 分支2
  }
} else {
  // 分支1、2都不成立
}

汇聚规则:不存在激活的节点能到达网关时,即可往后执行

循环 ​

使用多实例方式实现循环逻辑

类似Java逻辑如下:

java
for(Object item: items) {
  // 业务逻辑
}

for(int i = 0; i < items.size(); i++){
  Object item = items[i];
  // 业务逻辑
}

多实例特征中,可以使用跳过条件来实现continue,使用完成条件实现 break

多实例子流程中,也可以使用空结束事件和终止结束事件,分别实现循环中的 continue 和 break

类似Java逻辑如下:

java
for(int i = 0; i < items.size(); i++){
  Object item = items[i];
  if (conditionA) {
    continue; // 空结束事件
  }
  ...
  if (conditionB) {
    break; // 终止结束事件
  }
  ...
}

代码块/内部方法 ​

循环过程中,经常需要组合各种逻辑,此时可以使用子流程 SubProcess 实现

类似Java逻辑如下:

java
for(Object item: items){
  // 代码块开始
  item.disabled = false;
  list.add(item)
  ...
  // 代码块结束
}

返回 ​

多分支场景时,可以采用终止结速事件来实现返回

类似Java逻辑如下:

java
if (condition){
  return;
}
...

异常 ​

组件执行有异常时,会触发对应的错误边界事件,没有定义错误边界事件时,会抛出异常;

类似Java逻辑如下:

java
try {
  // 业务逻辑
} catch (Exection e) {
  if (有对应的错误边界事件) {
    // 触发错误边界事件
  } else {
    throw e;
  }
}

通过错误结束事件,可以实现抛出自定义事件

类似Java逻辑如下:

java
  throw new Exception('错误code')

事件 ​

信号抛出中间事件和信号捕获中间事件,可以实现监听指定事件并执行对应逻辑的能力。信号默认在全局范围内传播,所有进程都可以监听到,可以通过设置scope值为processInstance将信号限制在一个Process实例中。

类似Java逻辑如下:

java
public class EventManager {  
    private List<EventObserver> observers = new ArrayList<>();  
  
    public void addObserver(EventObserver observer) {  
        observers.add(observer);  
    }  
  
    public void removeObserver(EventObserver observer) {  
        observers.remove(observer);  
    }  
  
    public void notifyObservers(String eventName) {  
        for (EventObserver observer : observers) {  
            if (observer.getEventName().equals(eventName)) {  
                observer.execute();  
            }  
        }  
    }  
}  
...
class MsgNameObserver implements EventObserver {  
    @Override  
    public String getEventName() {  
        return "msgName";  
    }  
  
    @Override  
    public void execute() {  
        // 你的逻辑代码  
    }  
}
...
EventManager eventManager = new EventManager();  
MsgNameObserver msgNameObserver = new MsgNameObserver();  
eventManager.addObserver(msgNameObserver);  // 监听事件
eventManager.notifyObservers("msgName");    // 触发事件

延时执行 ​

定时器捕获中间事件,可以实现延时执行

类似Java逻辑如下:

java
Thread.sleep(1000);

如果是需要异步等待一定时间或定时执行逻辑,就教用定时执行Service

调用API ​

提供组件,实现各种类型的API调用

调用其他Service ​

使用CallAcivity组件,实现调用其他Service

事务 ​

一个进程可以设定启用事务,当进程中局部组件需要独立事务时,可采用事务子流程。 针对一个事务范围内的所有数据库操作组件,如果共用一个数据源的,采用本地事务,否则采用JTA事务。

超时 ​

一个进程可以设定超时时间,当时间超时后,进程中的组件将不再执行,并抛出超时异常。

每个组件也可以设置超时时间,当时间超时后,组件内部逻辑将不再执行(需要组件支持),多实例时,设置的超时时间为所有实例执行完成的时间,超时后,后续实例将不再执行,并抛出超时异常。

定时执行 ​

由统一的任务调度服务管理所有进程的定时执行。也可以用API调用组件来自动添加、删除定时任务。

全局事件 ​

由统一的事件总线完成,可以设置监听事件来启动进程执行。也可以用API调用组件来自动注册和触发事件。

进程的定义 ​

像流程图一样,把多个可重用的组件连接成一个数据流图,即可定义一个进程,示例如下:

XML定义 ​

参考 BPMN 定义规范,逻辑编排相关定义如下:

名称节点名说明
进程Process每个逻辑编排一个进程
顺序流SequenceFlow组件执行顺序,有条件判断是否可以通行

网关 ​

名称节点名说明
排他网关ExclusiveGateway条件判断
并行网关ParallelGateway无异步任务时,和顺序执行没有差异
包容网关InclusiveGateway多分支条件同时满足的情况

事件 ​

名称节点名说明
开始事件StartEvent逻辑编排入口,仅一个
结束事件EndEvent结束节点,可多个
终止结束事件流程或子流程实例强制结速
信号捕获中间事件监听信号(全局或进程实例内)
信号抛出中间事件触发信号(全局或进程实例内)

组件 ​

名称节点名说明
执行SQLSQLTask编码、名称、入口、出口、跳过执行表达式
单表操作TableTask
接口调用APITask
脚本执行GroovyTask
内嵌子流程SubProcess
调用子流程CallActivity
事务子流程Transaction

边界事件 ​

名称节点名说明
错误边界事件BoundaryEvent编码、名称、出口

逻辑编排场景分析 ​

顺序执行场景 ​

组件按顺序执行

分支场景

根据动作不同,可以转移到不同的状态

带条件的转移场景

动作发生后,根据转移条件,转移到不同的状态

退回场景1:使用不同状态标记退回数据

使用一个新状态来表示退回状态

退回场景2:使用相同状态标记退回数据

使用原状态,但用一个退回状态标记来表示退回状态

逻辑编排的使用 ​

执行逻辑流 ​

java
public static void start(String logicFlowCode, DelegateExecution execution)