轻量流程引擎接口设计

接上文,业务应用和流程引擎之间以及流程引擎和业务服务组件之间通过良好定义的接口进行交互。

业务应用和流程引擎之间的接口称为北向接口,流程引擎和业务组件之间的接口称为南向接口,流程引擎的其他接口如管理接口在此忽略。

1.北向接口

北向接口主要是事件引擎提供的面向业务应用的接口(我们的事件引擎是一个简单的事件引擎,用来接收事件、派发和管理事件。业务复杂后可采用复杂事件处理CEP),主要是事件通道(EventChannel)和业务事件。

事件通道是事件引擎提供的接口,用来接收业务应用的业务事件,业务应用通过事件通道交付业务事件。

业务事件分为同步事件和异步事件。业务应用交付同步事件时需要等待业务服务组件处理完毕后才返回,异步事件只要交付到事件引擎就立即返回,不必等待事件处理完毕。异步事件处理完后将事件处理结果通知流程引擎。

1.1业务事件类层次


BusinessEvent类

该类采用范型定义如下:

//ResultDto为事件处理器(EventHandler)方法的返回值类型,BusinessDataDto为业务数据类

public abstract class BusinessEvent <ResultDto,BusinessDataDto> {  
    private String processName;  //流程名称
    private Integer  businessKey;  //业务key,对我们的应用来讲,就是交易id(tradeId),为了BusinessEvent通用性,其类型也可范型化。
    private String eventType; //事件类型id
    private BusinessDataDto businessData ; //事件包含的业务数据,对下单事件,为下单时的订单OrderDto

    private String  role; //触发事件的角色,如buyer(买家)、seller(卖家)、timer(超时定时器)等

    private int actorId;  //事件触发人的id,在我们的系统中,主要用于买卖家

    private Date eventTime; //触发事件时间

    private String eventSource; //事件源

    private String eventSerial; //事件流水号,唯一,类似uuid

    private long workItemId; //工作项id

    private bool isInitialEvent;//是否初始事件,初始事件(位于开始节点中的事件)用来指示流程引擎创建新的流程实例。

   public BusinessEvent(String eventType,Integer businessKey,BusinessDataDto businessData){
         ...
    }


    ...

   
   /*deliver方法用来交付事件,就是将事件通过事件通道传给事件引擎*/

    public abstract ResultDto  deliver();
}

同步事件类SyncBusinessEvent

public class SyncBusinessEvent <ResultDto,BusinessDataDto> extends BusinessEvent <ResultDto,BusinessDataDto>{       

   public SyncBusinessEvent(String eventType,Integer businessKey,BusinessDataDto businessData){
         ...
    }
   
   /*将事件通过事件通道传给事件引擎,并等待事件处理结果*/
    public ResultDto  deliver(){
        //获取事件通道eventChannel

       EventChannel eventChannel = EventChannelFactory.getEventChannel();
       return (ResultDto) eventChannel.syncSend(this);   //同步发送事件,返回事件处理结果。

    }
}

使用方法如下:

/*买家在前台业务应用中下单时,业务应用创建下单事件,PlaceOrderResult,OrderDto均为业务应用的具体Java类

下单事件为启动流程的初始事件,没有businessKey,所以构造函数第二个参数传null。返回值类型PlaceOrderResult中包含有businessKey,就是tradeId属性,初始事件处理拦截器中需要用到该属性来建立businessKey和流程实例id的绑定关系*/

BusinessEvent <PlaceOrderResult,OrderDto> event =  new SyncBusinessEvent<PlaceOrderResult,OrderDto>("submitOrder",null,orderDto);
  //调用deliver方法交付事件,得到下单处理结果

PlaceOrderResult  result = event.deliver();

在实际应用中,可以为每个流程从该类再派生一个子类,在每个子类中为processName赋值(写死为对应的流程)。

异步事件类AsyncBusinessEvent

public class AsyncBusinessEvent <BusinessDataDto> extends BusinessEvent <Boolean,BusinessDataDto>{       

   public AsyncBusinessEvent(String eventType,Integer businessKey,BusinessDataDto businessData){
         ...
    }
   
   /*交付事件,不等待事件处理结果。

        返回值为TRUE表示事件引擎已成功接收异步事件

  */

      public Boolean  deliver(){
        //获取事件通道eventChannel

       EventChannel eventChannel = EventChannelFactory.getEventChannel();

       return (Boolean) eventChannel.asyncSend(this);   //异步发送事件,事件引擎收到就返回,不返回事件处理结果。

    }
}

交付异步事件的demo如下:

BusinessEvent<Boolean,XXXDto>  event = new AsyncBusinessEvent<XXXDto>(......);  //XXXDto为一个具体的java类

Boolean deliverResult = event.deliver();

1.2事件通道EventChannel接口

事件通道用来接收业务应用 交付(deliver)的业务事件,它提供两个方法syncSend和asyncSend,分别用来同步发送和异步发送事件。

北向接口还包括查询流程实例当前状态的接口和根据角色查询节点url的接口(例如买家和买家在同一个流程节点可以有不同的html页面url来操作和查看订单与交易)。

2.南向接口

南向接口为业务服务组件的接口,流程引擎根据事件中的eventType属性调用对应的业务组件接口方法(在流程定义文件中eventHanderMap中定义了每种eventType对应的业务组件和事件处理方法名)。

可以统一定义一个泛型的业务组件接口(事件处理接口),例如定义一个含有handleEvent方法的EventHandler接口,这样下单事件和确认收货事件的事件处理方法名都是handleEvent,这种方式的一个缺点是业务语义太弱,从方法名上无法区分是下单还是确认收货。另一种方法是自由个性化定义,不定义统一的业务组件接口,这样每个事件的事件处理方法名可不一样,例如下单事件的方法名为placeOrer,业务语义很强。
A)南向接口统一定义(泛型),接口如下:
interface BusinessEventHandler<ResultDto,BusinessDataDto>{
        ResultDto  handleEvent(BusinessDataDto);
}

所有的业务组件均实现该接口。

B)自由个性化定义

   对处理下单事件的业务服务组件,其处理下单事件的placeOrder方法签名可能定义如下(自由定义):

    interface PlaceOrderService{

    //  该方法值返回类型PlaceOrderResult和OrderDto参数类型和 1.1下单事件BusinessEvent中的类型要一致

    public  PlaceOrderResult  placeOrder(OrderDto orderDto) {

             ...

     }

     ...

 
可见handleEvent方法的业务语义没有placeOrder方法强。

3.初始事件的处理

 事件类中的processName(流程名称)加上businessKey可唯一映射到一个流程实例id,业务应用和业务服务组件通常不关注流程实例id,也就是希望流程实例id是透明的。

  为了保持透明,需要在初始事件(开始节点中的事件为初始事件,流程引擎为初始事件创建流程实例)处理中建立processNme+businessKey与流程实例id的绑定关系。

  为了建立绑定关系,在开始节点的事件eventHandler中配置拦截器,从eventHandler的返回值属性中得到businessKey。

猜你喜欢

转载自wanshi.iteye.com/blog/1310898
今日推荐