订单状态机设计

状态机整体设计:

 

说明:

  1. 基本要素:状态(state)、事件(event)、流转(transition)、虚拟状态(virtual state)、条件(guard)、条件分支、默认分支;
  2. 基本流程:图中"开始"状态接收到事件"E1"后切换至"S1"状态,完成一次状态流转;
  3. 自转场景:图中"S1"接收"E11"后状态未发生改变,同样视为完整一次状态流转;
  4. 分叉场景:图中"S1"到"S21"或"S22"的状态实际流转需要根据不同的条件选择,这里插入一个虚拟状态"选择状态1","S1"到"选择状态1"的流转由事件"E2"触发,而"选择状态1"到"S21"或"S22"的流转则由于虚拟状态的存在自动进行;
  5. 子任务场景:图中"S3"到"S4"的流转需要多个"E4"事件触发,这里同样插入虚拟状态"选择状态2"来实现,不同的是将默认分支回溯到"S3"。

单个流程详细实现

1.同步调用

2.异步调用


图中按时间顺序包含两个部分:业务端发送事件并返回结果、状态机处理事件回调业务系统完成状态流转,两个部分分别在两个数据库事务中。

条件动态设计方案——表达式语言

       状态机的应用需要各自业务系统根据自身的业务逻辑动态设计,对于状态机中逻辑条件的实现,这里选择使用java表达式语言,备选方案有Spring Expression Language(以下简称SpEL)和MVEL。
        根据官方文档介绍,SpEL的诞生是为了给Spring社区提供一种能够与Spring生态系统所有产品无缝对接,能提供一站式支持的表达式语言。考虑到Spring的框架的应用,SpEL是是最合适的选择,后续研究发现在以下场景中支持不友好:订单存在子订单,并且订单状态需要根据所有子订单的信息来综合考虑流转情况,SpEL实现遍历集合的方案是通过注册函数使用Java Stream的方式,与MVEL支持原生foreach循环相比复杂极大提高,而考虑到状态机条件使用场景,最终选择MVEL的方式。

状态机设计交互数据格式

{

    "smInfo": {

        "smId"null// long 状态机id,保存时需要,新增时为空

        "flowId"null// long 流程id

        "version"null// string 版本

        "smStatus"null// integer 状态机状态(1:测试中,2:已发布,3:已上线,4:已停用)

        "creator"null// string 创建人

        "modifier"null // string 修改人

    },

    "smStates": [{

        "stateId"null// long 状态id,保存时需要,新增时为空

        "stateValue"null// string 状态值,状态唯一编码,同一个状态机下 不可重复

        "stateDesc"null// string 状态描述

        "stateType"null// integer 状态类型:1常规状态,2选择状态

        "smId"null// long 状态机id

    }],

    "smTransitions": [{

        "transitionId"null// long 流转id,保存时需要,新增时为空

        "transitionDesc"null// string 流转描述:便于标识流转,存在事件的时候建议跟事件描述一致

        "smId"null// long 状态机id

        "eventValue"null// string 事件值(code)

        "eventDesc"null// string 事件描述

        "eventRole"null// integer 事件角色,多个角色可以使用逗号隔开:1卖家(商家),2买家(用户)

        "showCondition"null// string 事件是否显示mvel条件

        "sourceState"null// string 源状态值

        "targetState"null// string 目标状态值

        "caseCondition"null// string 分支mvel条件(源状态为虚拟状态时有效)

        "caseOrder"null// integer 分支顺序

        "caseDefault"null// integer 是否默认分支:1是,2否

        "guardCondition"null// string 约束条件

        "transitionAction"null// string 回调业务系统对应接口http地址

    }]

}

基本的状态机中插入规则引擎的方式来实现分叉场景,备选方案有Drools、Easy Rules、RuleBook。

名称是否开源stars/forkslast_modified复杂度github地址
Drools1393/13412018/4/24高,配置规则的时候需要新增指定格式文档https://github.com/kiegroup/drools
Easy Rules770/2172018/4/20低,支持字符串创建规则,支持表达式语言https://github.com/j-easy/easy-rules
RuleBook217/412018/4/21低,支持Lambda表达式,https://github.com/rulebook-rules/rulebook

其中Easy Rules复杂度低,而且提供了MVEL的方式支持字符串的配置,鉴于此,对于相对简单而且需要UI页面的配置方式的场景来说,Easy Rules是最合适的选择,另外对应开源代码的显示,还可以很方便地扩展成支持其他EL表达式语言,如上面提到的Spring EL。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值