管道流创建订单

随着现在的电商平台的日新月异,对于其下单流程来说,订单类型众多,且链路非常长。比如有解析购物车、获取用户地址信息、出仓、拆单、合单、计算运费、使用优惠券、组装订单信息、插入数据库...等等操作链路。

由于三月份的时候公司需要做B2C的需求,相当于一套新的生态链。而原先公司的基础设施实在不敢恭维。比如创建订单接口。所有类型的创建订单都由这个接口实现(里面大量的if else)。算上抽出来的代码,整个流程有上万行代码。如果要在上面强行接入B2C创建订单逻辑,无疑会牵一发而动全身。

所以急需准备一套低耦合的创建订单代码。主要目的是将每种类型的订单分开,并且能共用的共用(比如所有类型的订单都会有插入OrderDO这个操作)。

一开始我的想法是用策略模式+模板方法来做。策略模式用来路由订单类型,而模板方法用来提取公共方法或者重写自己特定的逻辑。然而这样做,底层的抽象类包含了所有订单类型的方法合集,严重耦合。且基本所有方法都需要重写,并且只能按底层执行方法提供的顺序来执行(除非你重写执行方法)。这种策略模式+模板方法其实只适用于比较简单的多类型业务。

通过请教以前老大。并在他的指引下,最终采用了策略模式+模板方法+责任链模式的设计思想。责任链模式借鉴了netty中的pipiline。

https://github.com/chenshengyue/pipeline

1.核心组件类型(core包)

1.1 AbstractPipe(抽象管道)

每个具体的管道都继承它。

每个管道所经历的流程

  • 根据入参判断是否被过滤

  • 执行具体业务

  • 调用下一个管道

      public void invoke(InvocationChain<T, S> invocationChain) {
    
      T parameter = invocationChain.getParameter();
      S context = invocationChain.getContext();
    
      //判断是否过滤此管道
      if (isFilter(parameter, context)) {
          log.info("{} ---> filter pipe : {}",
                  invocationChain.getKey(), this.getClass().getSimpleName());
    
      } else {
    
          rollbackAdd(invocationChain);
          
          //执行具体业务
          bizHandler(parameter, context);
    
          successAdd(invocationChain);
    
      }
    
      //调用下一个管道
      invocationChain.invokeNext();
    

    }

1.2 Success && RollBack (这点不是主要组件)

成功接口和回滚接口。两个接口都作用于pipe。

在整个pipeline执行过程中:

每个pipe执行前都会记录到InvocationChain.rollBackList。

每个pipe成功执行后都会记录到InvocationChain.successList

若整个pipeline执行失败,会遍历rollBackList并执行rollBack方法

无论pipeline执行是否成功,都会会遍历successList并执行success方法

1.3 Pipeline(管道流)&& InvocationChain(执行链)

PipelineImpl

  • 属性pipeList: 存储这个管道流所加载的管道

  • 内部私有类InvocationChainImpl: 一个PipeLine实例对应一个InvocationChain执行链。用于递归执行各个管道

      /**
       * 管道流执行入口
       */
      @Override
      public void invoke() {
    
          executedIndex = -1;
          log.info("{} : begin invoke...request = {}", key, JSON.toJSONString(this.getParameter()));
    
          invokeNext();
      }
    
      /**
       * 递归调用管道
       */
      @Override
      public void invokeNext() {
    
          executedIndex++;
          if (executedIndex < pipeList.size()) {
              Pipe pipe = pipeList.get(executedIndex);
    
              pipe.invoke(this);
          }
    
      }
    

1.4 AbstractEngineExecutor(抽象引擎执行器)

每个业务引擎都应继承AbstractEngineExecutor。
实现了InitializingBean,初始化pipeline。

运行时调用doPipeline方法

  • 校验入参
  • 实例化一个执行链
  • 执行管道流入口方法(invoke)

1.5EngineResolver

通过策略模式找到对应的引擎执行器。

策略模式参考我的这篇文章:https://www.cnblogs.com/chenshengyue/p/10826087.html

2.运行

启动项目。输入http://localhost:8080/swagger-ui.html#/

选择对应的controller,输入入参(创建订单类型为1的订单)

{ "addressId": 0, "bargainInfoId": 0, "cartId": 0, "orderType": 1, "skuInfoList": [ { "num": 0, "skuId": 0 } ], "userId": 0 }
看到运行结果

avatar

结合代码debug一下就能看懂!

posted @ 2019-09-18 20:12  chenshengyue  阅读(768)  评论(1编辑  收藏  举报