作者:Tom哥
公众号:微观技术
博客:https://offercome.cn
人生理念:知道的越多,不知道的越多,努力去学
作为软件架构师,当面对复杂的业务逻辑,我们常用的解决方案就是拆分
以流量网关为例:
我们会定义 Filter
接口,子类通过实现 filter()
方法来满足自己的业务逻辑,如:限流逻辑
、鉴权逻辑
等,如果某些业务流程不需要执行该 Filter
组件,我们可以在 isSkip
方法里定义跳出逻辑,直接跳过该组件,继续执行下一个组件。
最后我们定义了这么多的 Filter 组件,通过 Spring 框架扫描优先级注解,完成了组件链的串联。
当然这个编排比较单一,不够灵活。无法实现一些串行
、并行
的自由组合。
比如,我们面对上图这样的业务流程该如何应对?是自己借助 JUC 并发包以及各种 if else 定制化实现流程控制吗?
另外,随着业务后续迭代,这些任务间的关系还会发生变化,每次都去改动代码,违反软件的开闭原则
,很容易发生线上故障。
**🚀 给大家推荐一款轻量级的流程引擎 **
LiteFlow 是一款国产开源的,具有轻量,快速,稳定可编排的组件式规则引擎,帮助我们拆解实现各种复杂的业务逻辑,开箱即用,上手容易。
LiteFlow 设计了非常强大的规则表达式,一切复杂的流程在 LiteFlow 表达式的加持下,都异常丝滑简便。
我们来一起看下 EL 规则的写法
依次执行 a、b、c、d四个组件,用 THEN 关键字
<chain name="chain1">
THEN(a, b, c, d);
</chain>
并行执行a、b、c三个组件,用WHEN
关键字
<chain name="chain1">
WHEN(a, b, c);
</chain>
根据组件 a 的运行结果,选择执行 b、c、d 中的一个,用 SWITCH
关键字
<chain name="chain1">
SWITCH(a).to(b, c, d);
</chain>
条件编排就是变成语言中的 if else,使用 IF 关键字
其中 x 为条件节点,为真的情况下,执行链路就为x->a->c,为假链路就为x->b->c
<chain name="chain1">
THEN(
IF(x, a, b),
c
);
</chain>
比如,我们要实现这样一个复杂的流程
对应的 EL 表达式为:
<chain name="chain1">
IF(x1, a).ELIF(x2, b).ELIF(x3, c).ELIF(x4, d).ELSE(THEN(m, n));
</chain>
当遇到一些复杂的业务,表达式嵌套多层,很不直观,我们可以先定义子流程,然后在主流程中引用。这样逻辑会比较清晰
定义子流程 sub_chain
,串行执行 a、b 两个组件
<chain name="sub_chain">
THEN(a,b);
</chain>
然后,在主流程中引入之前定义的子流程 sub_chain
<chain name="mainChain">
WHEN(
sub_chain,
c,d
);
</chain>
看完介绍是不是很手痒,接下来我们就以一个电商的 订单价格计算 为例子,讲解下 LiteFlow 如何使用
首先,我们看下订单价格计算接口 都涉及哪些业务逻辑,为了快速切入,画了个流程图便于大家理解
毕竟,一图胜千言哈
以 Spring Boot 应用为例,首先在 pom.xml 文件添加下面的依赖
修改 application.yml 配置文件,添加 LiteFlow 的规则文件路径
定义组件,继承 NodeComponent 类 ,并重写 process() 方法,里面实现自己负责的业务逻辑,比如:促销满减计算、会员折扣计算、运费计算等
通过重写 isAccess() 方法来决定是否执行该组件
MemberDiscountCmp 负责会员折扣计算,根据 memberCode 查询会员等级,并获取对应的会员折扣,然后计算订单可以减免多少优惠
PostageCondCmp 组件比较特殊,根据 是否境外购 选择对应的运费计算组件,继承了 NodeSwitchComponent ,并实现了 processSwitch() 方法
其他业务组件 基本类似,就不一一介绍了,感兴趣的同学可以自己看下代码
所有组件实例无缝支持 Spring 框架,通过@Component
注解标识,所有的Bean实例全部交由 Spring 容器统一管理
定义好组件后,接下来就要编写 EL 规则表达式,将所有的流程关联起来
最后,启动 Spring Boot 工程,访问地址:http://localhost:8580/