设计模式——管道模式(二)

管道配置:

package org.example.design.pipeline;

import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.List;

/**
 * Description: 供应商调用管道
 *
 */
@Slf4j
public class Pipeline {

    private List> steps = new ArrayList<>();

    /**
     * 增加步骤
     *
     * @param step 步骤
     * @return this
     */
    public Pipeline next(Step step) {
        steps.add(step);
        return this;
    }

    /**
     * 执行步骤
     *
     * @param context 执行内容
     */
    public void execute(ProcessContext context) {
        log.info("{}--管道执行开始--订单号:{}", context.getSupplierProcess(), context.getOrderNo());

        for (Step step : steps) {
            step.next(context);

            if (PipelineContextHolder.getAndRemoveBreakFlag()) {
                break;
            }
        }
        log.info("管道执行结束");
    }
}
package org.example.design.pipeline;

import org.springframework.core.NamedThreadLocal;

/**
 * 管道上下文保持器
 *
 */
public class PipelineContextHolder {

    // 中断标识
    private static ThreadLocal breakFlag = new NamedThreadLocal<>("管道中断标识");

    public static void putBreakFlag(Boolean flagValue) {
        breakFlag.set(flagValue);
    }

    static boolean getAndRemoveBreakFlag() {
        try {
            Boolean result = breakFlag.get();
            if (result != null) {
                return result;
            }
            return false;
        } finally {
            breakFlag.remove();
        }
    }

}
package org.example.design.pipeline;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.example.design.pipeline.zhichong.OrderInfo;
import org.example.design.pipeline.zhichong.SupplierProcessEnum;

/**
 * Description:管道上下文
 */
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class ProcessContext {

    /**
     * 订单
     */
    private OrderInfo orderInfo;

    /**
     * 流程标识
     */
    private SupplierProcessEnum supplierProcess;

    /**
     * 回调参数
     */
    private Object callback;

    public String getOrderNo() {
        return orderInfo.getOrderNo();
    }
}
package org.example.design.pipeline;

/**
 * Description: 步骤
 *
 */
public interface Step {

    S getCur();

    /**
     * 转换到下一个状态
     *
     * @param context 下一步
     */
    void next(ProcessContext context);
}


package org.example.design.pipeline;

import lombok.extern.slf4j.Slf4j;
import org.example.design.pipeline.zhichong.OrderInfo;
import org.example.exception.ServiceException;
import org.springframework.beans.factory.annotation.Value;

/**
 * Description: 查询订单步骤
 */
@Slf4j
public abstract class YCAbstractStep implements Step {

    @Value("${yuecheng.exe.num:3}")
    private int maxExeNum;

    @Override
    public void next(ProcessContext context) {
        log.info("步骤 {} 开始执行,context:{}", getClassName(), context.getOrderNo());
        OrderInfo orderInfo = context.getOrderInfo();
        try {
            //判断是否执行该步骤
            if (!verificationStatus(orderInfo)) {
                return;
            }
            //调用次数过多直接挂起
            if (null != orderInfo.getSupplierExeNum() && orderInfo.getSupplierExeNum() >= maxExeNum) {
                autoSuspend(orderInfo);
                return;
            }
            //核心处理
            handle(context, orderInfo);
        } catch (ServiceException e) {
            addExeNum(orderInfo);
            throw e;
        } catch (Exception e) {
            log.error("跃程调用供应商接口出现异常name:{},order:{}", getClassName(), context.getOrderNo(), e);
            throw e;
        }
        log.info("步骤 {} 执行执行完成", getClassName());
    }

    public abstract boolean verificationStatus(OrderInfo orderInfo);

    public abstract void autoSuspend(OrderInfo orderInfo);

    public abstract void handle(ProcessContext context, OrderInfo orderInfo);

    public abstract String getClassName();

    public abstract void addExeNum(OrderInfo orderInfo);
}

package org.example.design.pipeline;

import org.example.design.pipeline.zhichong.SupplierProcessEnum;

import java.util.HashMap;
import java.util.Map;

/**
 * Description: 供应商注册器
 */
public class SupplierRegistry {

    private static SupplierRegistry instance = new SupplierRegistry();

    private Map registry = new HashMap<>();

    private SupplierRegistry() {
    }

    public static SupplierRegistry getInstance() {
        return instance;
    }

    public void register(SupplierProcessEnum supplierProcess, Object process) {
        registry.put(getCapitalCode(supplierProcess), process);
    }

    @SuppressWarnings("unchecked")
    public  T getCallSupplierProcess(SupplierProcessEnum supplierProcess) {
        return (T) registry.get(getCapitalCode(supplierProcess));
    }


    private String getCapitalCode(SupplierProcessEnum supplierProcess) {
        return String.format("%s_%s", supplierProcess.getSupplierNo(), supplierProcess.getProcessName());
    }


}


package org.example.design.pipeline;

import org.example.design.pipeline.process.DirectRechargeProcess;
import org.example.design.pipeline.zhichong.SupplierProcessEnum;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;

/**
 * 供应商注册
 */
@Component
public class YCStartup {

    @Resource
    private DirectRechargeProcess directRechargeProcess;
    //@Resource
    //private ReceiverCardProcess receiverCardProcess;
    //@Resource
    //private GameRechargeProcess gameRechargeProcess;

    @PostConstruct
    public void init() {
        SupplierRegistry.getInstance().register(SupplierProcessEnum.YC_DR, directRechargeProcess);
        //SupplierRegistry.getInstance().register(SupplierProcessEnum.YC_RC, receiverCardProcess);
        //SupplierRegistry.getInstance().register(SupplierProcessEnum.YC_GR, gameRechargeProcess);
    }
}

处理器:

package org.example.design.pipeline.process;

import org.example.design.pipeline.ProcessContext;

/**
 * Description:调用供应商接口
 *
 */
public interface CallSupplierProcess {

    /**
     * 发货流程
     *
     * @param context 流程信息
     */
    void deliverGoods(ProcessContext context);
}




package org.example.design.pipeline.process;

import org.example.design.pipeline.Pipeline;
import org.example.design.pipeline.ProcessContext;
import org.example.design.pipeline.zhichong.DRQueryOrderStep;
import org.example.design.pipeline.zhichong.DRSubmitOrderStep;
import org.example.design.pipeline.zhichong.OrderStatusEnum;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;

/**
 * Description:直冲
 *
 */
@Component
public class DirectRechargeProcess implements CallSupplierProcess {

    @Resource
    private DRSubmitOrderStep drSubmitOrderStep;
    @Resource
    private DRQueryOrderStep drQueryOrderStep;

    private Pipeline pipeline;

    @PostConstruct
    public void init() {
        pipeline = new Pipeline().next(drSubmitOrderStep).next(drQueryOrderStep);
    }

    @Override
    public void deliverGoods(ProcessContext context) {
        pipeline.execute(context);
    }
}

具体步骤:

package org.example.design.pipeline.zhichong;

import lombok.extern.slf4j.Slf4j;
import org.example.design.pipeline.PipelineContextHolder;
import org.example.design.pipeline.ProcessContext;
import org.example.design.pipeline.YCAbstractStep;
import org.springframework.stereotype.Component;

/**
 * Description: 查询订单步骤
 */
@Slf4j
@Component
public class DRQueryOrderStep extends YCAbstractStep {


    @Override
    public OrderStatusEnum getCur() {
        return OrderStatusEnum.ING_SEND;
    }

    @Override
    public boolean verificationStatus(OrderInfo orderInfo) {
        return true;
    }

    @Override
    public void autoSuspend(OrderInfo orderInfo) {
        // 具体业务逻辑
        //中断管道
        PipelineContextHolder.putBreakFlag(true);
    }

    @Override
    public void handle(ProcessContext context, OrderInfo orderInfo) {
    }

    @Override
    public String getClassName() {
        return this.getClass().getName();
    }

    @Override
    public void addExeNum(OrderInfo orderInfo) {
    }
}
package org.example.design.pipeline.zhichong;

import lombok.extern.slf4j.Slf4j;
import org.example.design.pipeline.PipelineContextHolder;
import org.example.design.pipeline.ProcessContext;
import org.example.design.pipeline.YCAbstractStep;
import org.springframework.stereotype.Component;

/**
 * Description: 直冲类提交订单步骤
 */
@Slf4j
@Component
public class DRSubmitOrderStep extends YCAbstractStep {


    @Override
    public OrderStatusEnum getCur() {
        return OrderStatusEnum.WAIT_SEND;
    }

    @Override
    public boolean verificationStatus(OrderInfo orderInfo) {
        return true;
    }

    @Override
    public void autoSuspend(OrderInfo orderInfo) {
        // 具体业务逻辑
        //中断管道
        PipelineContextHolder.putBreakFlag(true);
    }

    @Override
    public void handle(ProcessContext context, OrderInfo orderInfo) {

    }

    @Override
    public String getClassName() {
        return this.getClass().getName();
    }

    @Override
    public void addExeNum(OrderInfo orderInfo) {
        ;
    }
}

业务相关:

package org.example.design.pipeline.zhichong;

import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.*;
import lombok.experimental.Accessors;

import java.math.BigDecimal;
import java.util.Date;

/**
 * 

* 商品订单表 *

* @author mybatis-plus-generator */ @Data @Builder @NoArgsConstructor @AllArgsConstructor @Accessors(chain = true) @TableName("demo_order_info") @ApiModel(value = "OrderInfo对象", description = "商品订单表") public class OrderInfo { private static final long serialVersionUID = 1L; @ApiModelProperty(value = "订单编号") @TableId("order_no") private String orderNo; @ApiModelProperty(value = "订单状态") @TableField("order_status") private Integer orderStatus; @ApiModelProperty(value = "每个流程子状态") @TableField("step_order_status") private Integer stepOrderStatus; @ApiModelProperty(value = "客户号") @TableField("cust_no") private String custNo; @ApiModelProperty(value = "商品ID") @TableField("goods_id") private String goodsId; @ApiModelProperty(value = "商品信息ID") @TableField("goods_info_id") private String goodsInfoId; @ApiModelProperty(value = "商品规格ID") @TableField("goods_spec_id") private String goodsSpecId; @ApiModelProperty(value = "规格参数,属性值ID逗号连接串") @TableField("spec_param") private String specParam; @ApiModelProperty(value = "商品名称") @TableField("goods_name") private String goodsName; @ApiModelProperty(value = "商品描述") @TableField("goods_desc") private String goodsDesc; @ApiModelProperty(value = "商品图片") @TableField("goods_pic") private String goodsPic; @ApiModelProperty(value = "商品类型") @TableField("goods_type") private String goodsType; @ApiModelProperty(value = "动态参数") @TableField("account_info") private String accountInfo; @ApiModelProperty(value = "动态返回结果") @TableField("return_info") private String returnInfo; @ApiModelProperty(value = "售价") @TableField("sale_price") private BigDecimal salePrice; @ApiModelProperty(value = "商品采购价") @TableField("goods_purchase_price") private BigDecimal goodsPurchasePrice; @ApiModelProperty(value = "购买数量") @TableField("purchase_num") private Integer purchaseNum; @ApiModelProperty(value = "商户号") @TableField("merchant_no") private String merchantNo; @ApiModelProperty(value = "外部订单号") @TableField("out_order_no") private String outOrderNo; @ApiModelProperty(value = "供应商商品id") @TableField("supplier_goods_id") private String supplierGoodsId; @ApiModelProperty(value = "调用供应商接口次数") @TableField("supplier_exe_num") private Integer supplierExeNum; @ApiModelProperty(value = "提交订单时间") @TableField("submit_datetime") private Date submitDatetime; @ApiModelProperty(value = "关闭订单时间") @TableField("close_datetime") private Date closeDatetime; @ApiModelProperty(value = "退款原因") @TableField("refund_reason") private String refundReason; @ApiModelProperty(value = "收货地址") @TableField("receive_address") private String receiveAddress; @ApiModelProperty(value = "收货人") @TableField("receive_name") private String receiveName; @ApiModelProperty(value = "手机号码") @TableField("receive_mobile") private String receiveMobile; @ApiModelProperty(value = "发货时间") @TableField("deliver_datetime") private Date deliverDatetime; @ApiModelProperty(value = "发货方式") @TableField("deliver_type") private String deliverType; @ApiModelProperty(value = "支付流水id") @TableField("pay_log_id") private String payLogId; @ApiModelProperty(value = "修改时间") @TableField("update_datetime") private Date updateDatetime; @ApiModelProperty(value = "创建时间") @TableField("create_datetime") private Date createDatetime; public static final String ORDER_NO = "order_no"; public static final String ORDER_STATUS = "order_status"; public static final String STEP_ORDER_STATUS = "step_order_status"; public static final String CUST_NO = "cust_no"; public static final String GOODS_ID = "goods_id"; public static final String GOODS_INFO_ID = "goods_info_id"; public static final String GOODS_SPEC_ID = "goods_spec_id"; public static final String SPEC_PARAM = "spec_param"; public static final String GOODS_NAME = "goods_name"; public static final String GOODS_DESC = "goods_desc"; public static final String GOODS_PIC = "goods_pic"; public static final String GOODS_TYPE = "goods_type"; public static final String ACCOUNT_INFO = "account_info"; public static final String RETURN_INFO = "return_info"; public static final String SALE_PRICE = "sale_price"; public static final String GOODS_PURCHASE_PRICE = "goods_purchase_price"; public static final String PURCHASE_NUM = "purchase_num"; public static final String MERCHANT_NO = "merchant_no"; public static final String OUT_ORDER_NO = "out_order_no"; public static final String SUPPLIER_GOODS_ID = "supplier_goods_id"; public static final String SUPPLIER_EXE_NUM = "supplier_exe_num"; public static final String SUBMIT_DATETIME = "submit_datetime"; public static final String CLOSE_DATETIME = "close_datetime"; public static final String REFUND_REASON = "refund_reason"; public static final String RECEIVE_ADDRESS = "receive_address"; public static final String RECEIVE_NAME = "receive_name"; public static final String RECEIVE_MOBILE = "receive_mobile"; public static final String DELIVER_DATETIME = "deliver_datetime"; public static final String DELIVER_TYPE = "deliver_type"; public static final String UPDATE_DATETIME = "update_datetime"; public static final String CREATE_DATETIME = "create_datetime"; } @AllArgsConstructor @Getter public enum OrderStatusEnum { WAIT_PAY(10, "待付款"), WAIT_SEND(20, "待发货"), ING_SEND(21, "发货中"), FINISH(30, "已完成"), CLOSED(31, "已关闭"), WAIT_REFUND(40, "待退款"), REFUND_PROCESS(41, "退款中"), REFUND_SUCCESS(42, "退款成功"), AUTO_SUSPEND(90, "自动挂起"), ; private Integer code; private String msg; public static OrderStatusEnum getEnum(Integer code) { for (OrderStatusEnum value : OrderStatusEnum.values()) { if (value.getCode().equals(code)) { return value; } } throw new IllegalArgumentException("枚举值不存在"); } } @AllArgsConstructor @Getter public enum SupplierProcessEnum { YC_DR("yuecheng", "yc_dr", "DirectRechargeProcess", "跃程", "跃程直充类"), YC_RC("yuecheng", "yc_rc", "ReceiverCardProcess", "跃程", "跃程提卡类"), YC_GR("yuecheng", "yc_gr", "GameRechargeProcess", "跃程", "跃程游戏充值类"), ; private String supplierNo; private String code; private String processName; private String supplierName; private String msg; public static SupplierProcessEnum getEnum(String code) { for (SupplierProcessEnum value : SupplierProcessEnum.values()) { if (value.getCode().equals(code)) { return value; } } throw new IllegalArgumentException("枚举不存在"); } public static SupplierProcessEnum getEnum(String supplierNo, String processName) { for (SupplierProcessEnum value : SupplierProcessEnum.values()) { if (value.getSupplierNo().equals(supplierNo) && value.getProcessName().equals(processName)) { return value; } } throw new IllegalArgumentException("枚举不存在"); } }

你可能感兴趣的:(设计模式)