在我们平时做项目的时候,经常会遇到复杂的业务逻辑,如果使用if else来实现的话,往往会很冗长,维护成本也很高。今天给大家推荐一个轻量级流程引擎LiteFlow,可以优雅地实现复杂的业务逻辑,本文将以电商项目中的订单价格计算为例来聊聊它的使用。
SpringBoot实战电商项目mall(50k+star)地址:github.com/macrozheng/…
LiteFlow是一个轻量且强大的国产流程引擎框架,可用于复杂的组件化业务的编排工作。通过它我们可以把业务逻辑都定义到不同组件之中,然后使用简洁的规则文件来串联整个流程,从而实现复杂的业务逻辑。
LiteFlow主要特性如下:
下面是使用LiteFlow来实现订单价格计算的展示页面,实现起来确实比较优雅!
LiteFlow还拥有自己的IDEA插件LiteFlowX,通过该插件能支持规则文件的智能提示、语法高亮、组件与规则文件之间的跳转及LiteFlow工具箱等功能,强烈建议大家安装下。
接下来我们学习下规则表达式,也就是规则文件的编写,入门表达式非常简单,但这对使用LiteFlow非常有帮助!
当我们想要依次执行a、b、c、d四个组件时,直接使用THEN关键字即可。
THEN(a, b, c, d);
复制代码
如果想并行执行a、b、c三个组件的话,可以使用WHEN关键字。
WHEN(a, b, c);
复制代码
如果想实现代码中的switch逻辑的话,例如通过a组件的返回结果进行判断,如果返回的是组件名称b的话则执行b组件,可以使用SWITCH关键字。
SWITCH(a).to(b, c, d);
复制代码
如果想实现代码中的if逻辑的话,例如当x组件返回为true时执行a,可以使用IF关键字。
IF(x, a);
复制代码
如果想实现if的三元运算符逻辑的话,例如x组件返回为true时执行a组件,返回为false时执行b组件,可以编写如下规则文件。
IF(x, a, b);
复制代码
如果想实现if else逻辑的话,可以使用ELSE关键字,和上面实现效果等价。
IF(x, a).ELSE(b);
复制代码
如果想实现else if逻辑的话,可以使用ELIF关键字。
IF(x1, a).ELIF(x2, b).ELSE(c);
复制代码
当某些流程比较复杂时,我们可以定义子流程,然后在主流程中引用,这样逻辑会比较清晰。
例如我们有如下子流程,执行C、D组件。
THEN(C, D);
复制代码
然后我们直接在主流程中引用子流程即可。
THEN(
A, B,
subChain,
E
);
复制代码
学习完规则表达式后,我们发现LiteFlow寥寥几个关键字,就可以实现复杂的流程了。下面我们将以订单价格计算为例,实践下LiteFlow这个流程引擎框架。
com.yomahub
liteflow-spring-boot-starter
2.8.5
复制代码
server:
port: 8580
liteflow:
#规则文件路径
rule-source: liteflow/*.el.xml
复制代码
gitee.com/bryan31/lit…
/**
* 优惠券抵扣计算组件
*/
@Component("couponCmp")
public class CouponCmp extends NodeComponent {
@Override
public void process() throws Exception {
PriceContext context = this.getContextBean(PriceContext.class);
/**这里Mock下根据couponId取到的优惠卷面值为15元**/
Long couponId = context.getCouponId();
BigDecimal couponPrice = new BigDecimal(15);
BigDecimal prePrice = context.getLastestPriceStep().getCurrPrice();
BigDecimal currPrice = prePrice.subtract(couponPrice);
context.addPriceStep(new PriceStepVO(PriceTypeEnum.COUPON_DISCOUNT,
couponId.toString(),
prePrice,
currPrice.subtract(prePrice),
currPrice,
PriceTypeEnum.COUPON_DISCOUNT.getName()));
}
@Override
public boolean isAccess() {
PriceContext context = this.getContextBean(PriceContext.class);
if(context.getCouponId() != null){
return true;
}else{
return false;
}
}
}
复制代码
/**
* 运费条件组件
*/
@Component("postageCondCmp")
public class PostageCondCmp extends NodeSwitchComponent {
@Override
public String processSwitch() throws Exception {
PriceContext context = this.getContextBean(PriceContext.class);
//根据参数oversea来判断是否境外购,转到相应的组件
boolean oversea = context.isOversea();
if(oversea){
return "overseaPostageCmp";
}else{
return "postageCmp";
}
}
}
复制代码
<?xml version="1.0" encoding="UTF-8"?>
THEN(fullCutCmp, fullDiscountCmp, rushBuyCmp);
复制代码
<?xml version="1.0" encoding="UTF-8"?>
THEN(
checkCmp, slotInitCmp, priceStepInitCmp,
promotionConvertCmp, memberDiscountCmp,
promotionChain, couponCmp,
SWITCH(postageCondCmp).to(postageCmp, overseaPostageCmp),
priceResultCmp, stepPrintCmp
);
复制代码
@Controller
public class PriceExampleController {
@Resource
private FlowExecutor flowExecutor;
@RequestMapping(value = "/submit", method = RequestMethod.POST)
@ResponseBody
public String submit(@Nullable @RequestBody String reqData) {
try {
PriceCalcReqVO req = JSON.parseObject(reqData, PriceCalcReqVO.class);
LiteflowResponse response = flowExecutor.execute2Resp("mainChain", req, PriceContext.class);
return response.getContextBean(PriceContext.class).getPrintLog();
} catch (Throwable t) {
t.printStackTrace();
return "error";
}
}
}
复制代码
public class PriceContext {
/**
* 订单号
*/
private String orderNo;
/**
* 是否境外购
*/
private boolean oversea;
/**
* 商品包
*/
private List productPackList;
/**
* 订单渠道
*/
private OrderChannelEnum orderChannel;
/**
* 会员CODE
*/
private String memberCode;
/**
* 优惠券
*/
private Long couponId;
/**
* 优惠信息
*/
private List promotionPackList;
/**
* 价格步骤
*/
private List priceStepList = new ArrayList<>();
/**
* 订单原始价格
*/
private BigDecimal originalOrderPrice;
/**
* 订单最终价格
*/
private BigDecimal finalOrderPrice;
/**
* 步骤日志
*/
private String printLog;
}
复制代码
/**
* Slot初始化组件
*/
@Component("slotInitCmp")
public class SlotInitCmp extends NodeComponent {
@Override
public void process() throws Exception {
//把主要参数冗余到slot里
PriceCalcReqVO req = this.getRequestData();
PriceContext context = this.getContextBean(PriceContext.class);
context.setOrderNo(req.getOrderNo());
context.setOversea(req.isOversea());
context.setMemberCode(req.getMemberCode());
context.setOrderChannel(req.getOrderChannel());
context.setProductPackList(req.getProductPackList());
context.setCouponId(req.getCouponId());
}
@Override
public boolean isAccess() {
PriceCalcReqVO req = this.getSlot().getRequestData();
if(req != null){
return true;
}else{
return false;
}
}
}
复制代码
LiteFlow确实是一款好用的轻量级流程引擎,可以让复杂的业务逻辑变得清晰起来,便于代码维护。它的规则文件比起其他流程引擎来说,编写简单太多了,几分钟就能上手,感兴趣的朋友可以尝试下它!
页面更新:2024-04-25
本站资料均由网友自行发布提供,仅用于学习交流。如有版权问题,请与我联系,QQ:4156828
© CopyRight 2020-2024 All Rights Reserved. Powered By 71396.com 闽ICP备11008920号-4
闽公网安备35020302034903号